My problem is this one I got a query that is like this:
SELECT ID FROM TABLE LEFT JOIN ANOTHERTABLE ON TABLE.ID=ANOTHERTABLE.ID WHERE TABLE.KEY='X' OR TABLE.KEY='Y' OR TABLE.KEY='Z';
When I play this query it will return more than one id... but 3 id are the same (because each condition pick it). I need to select the only id that show up multiple times but without using count... Basically I need to select the only ID that will be select by condition 1, 2 and 3. I don't really understand how to do it.
Do you know how?
EDIT. I was able to find a really strange solution that works but if you can make it easier to read please do it...
SELECT PC_ID
FROM A a
left join B b
on a.EDI_ID = b.ID
WHERE b.key='X' AND b.value='some'
AND a.PC_ID in (
SELECT PC_ID
FROM A a
left join B b
on a.EDI_ID = b.ID
where b.key='Y' AND b.value='something'
)
AND a.PC_ID in (
SELECT PC_ID
FROM A a
left join B b
on a.EDI_ID = b.ID
where b.key='Z' AND b.value='thing'
)
Maybe after this edit it will be easier to help me.
EDIT2.
I have two tables. My main table (B) contains three fields: ID, KEY and VALUE
My table (A) contains two fields: PC_ID (the id I want to select), EDI_ID (the id contained in the main table).
In my main table I am sure that by using key and value with 3 different values (which are passed to me from the frontend) all the IDs of my main table will have a match in my table A (there will therefore be an EDI_ID for each ID). And in turn PC_ID corresponding to the EDI_ID can have many values for each of the three conditions... but only one value will be the same for all three conditions.
So filtering in the main table (B) for key='X' value='condition1' I will get a series of ID.... This set of ID will always have a corresponding EDI_ID in table (A). There will then be a series of PC_ID values that correspond to each EDI_ID selected. Same thing happens for the condition key='Y' value='condition2' Same thing happens for the condition key='Z' value='condition3' But all three of these selects will have only one PC_ID value in common, which is the one I want to select. I hope it's clearer this way.
EDIT3. I made a postgres example of the dataset + query https://www.db-fiddle.com/f/redSAVfixCHUE4zPu5aAkk/11
But like I said in the comment the 3rd query this only works on db fiddle (maybe a difference between oracle and postgres? I'm not sure...)
#this is working here but not working on my real dataset
SELECT A.PC_ID FROM A
INNER JOIN B AS bx ON A.EDI_ID = bx.ID AND bx.KEYV = 'X' AND bx.valuev='some'
INNER JOIN B AS byy ON A.EDI_ID = byy.ID AND byy.KEYV = 'Y' AND byy.valuev='something'
INNER JOIN B AS bz ON A.EDI_ID = bz.ID AND bz.KEYV = 'Z' AND bz.valuev='thing';
the example dataset should be right but I really cannot be 100% sure, I did not make the original dataset so this is still my own interpretation of it. I hope this is a good way for anybody with more skill than me to find out why and how.
FINAL EDIT. I changed the dataset to actually fit what's inside my db: https://www.db-fiddle.com/f/redSAVfixCHUE4zPu5aAkk/15 basically what I did wrong yesterday and the reason why the last one did not work on real data was that EDI_ID always change, while there can be more than one PC_ID that's the same (it was the opposite of what I did yesterday). So no answer that I can use actually worked (not even the last one with LISTAGG). If you can fix it with the new dataset I will accept the first with an answer that actually work and that's different than mine and that don't use COUNT.
If you have duplicate pc_id
values then you can use:
SELECT a.pc_id
FROM a
INNER JOIN b
ON a.edi_id = b.id
WHERE (b.key, b.value) IN (
('X', 'some'), ('Y', 'something'), ('Z', 'thing')
)
GROUP BY a.pc_id
HAVING COUNT(DISTINCT b.key) = 3
or, without using COUNT
, you can use other aggregation functions:
SELECT a.pc_id
FROM a
INNER JOIN b
ON a.edi_id = b.id
WHERE (b.key, b.value) IN (
('X', 'some'), ('Y', 'something'), ('Z', 'thing')
)
GROUP BY a.pc_id
HAVING MAX(CASE b.key WHEN 'X' THEN 1 END) = 1
AND MAX(CASE b.key WHEN 'Y' THEN 1 END) = 1
AND MAX(CASE b.key WHEN 'Z' THEN 1 END) = 1
Or, from Oracle 12, MATCH_RECOGNIZE
for row-by-row pattern matching:
SELECT pc_id
FROM (
SELECT a.pc_id,
b.key
FROM a
INNER JOIN b
ON a.edi_id = b.id
WHERE (b.key, b.value) IN (
('X', 'some'), ('Y', 'something'), ('Z', 'thing')
)
)
MATCH_RECOGNIZE(
PARTITION BY pc_id
ORDER BY key
PATTERN (x+ y+ z+)
DEFINE x AS key = 'X',
y AS key = 'Y',
z AS key = 'Z'
)
Which, for your "final edit" sample data:
CREATE TABLE A (
PC_ID INT,
EDI_ID INT
);
CREATE TABLE B (
ID INT,
KEY VARCHAR(255),
VALUE VARCHAR(255)
);
INSERT INTO A (PC_ID, EDI_ID) VALUES (100,10), (100,12), (100,13), (101,20), (102, 30), (103,40), (12, 50),(324, 120);
INSERT INTO B (ID, KEY, VALUE) VALUES
(10, 'X', 'some'),
(12, 'Y', 'something'),
(13, 'Z', 'thing'),
(20, 'Z', 'thing'),
(30, 'Z', 'thing'),
(40, 'Z', 'thing'),
(50, 'Z', 'thing'),
(120, 'NO', 'nothing to see');
All output:
PC_ID |
---|
100 |