Given a parent table 'parent'
╔═══════════╦══════════╗
║ PARENT_ID ║ NAME ║
╠═══════════╬══════════╣
║ 1 ║ bob ║
║ 2 ║ carol ║
║ 3 ║ stew ║
╚═══════════╩══════════╝
and a many-many relationship table 'rel' between parent and a (here unspecified) property table
╔═══════════╦═══════════╗
║ PARENT_ID ║ PROP_ID ║
╠═══════════╬═══════════╣
║ 1 ║ 5 ║
║ 1 ║ 1 ║
║ 2 ║ 5 ║
║ 2 ║ 4 ║
║ 2 ║ 1 ║
║ 3 ║ 1 ║
║ 3 ║ 3 ║
╚═══════════╩═══════════╝
How can I select all parents that have all of a specified set of relationships? E.g. with the sample data, how can I find all parents that have both property 5 and 1?
edit: Same question but with requirement for an exact match: SQL Select only rows where exact multiple relationships exist
How to implement one-to-many relationships when designing a database: Create two tables (table 1 and table 2) with their own primary keys. Add a foreign key on a column in table 1 based on the primary key of table 2. This will mean that table 1 can have one or more records related to a single record in table 2.
The SQL IN OperatorThe IN operator allows you to specify multiple values in a WHERE clause.
The SQL EXCEPT operator is used to return all rows in the first SELECT statement that are not returned by the second SELECT statement. Each SELECT statement will define a dataset. The EXCEPT operator will retrieve all records from the first dataset and then remove from the results all records from the second dataset.
This is called Relational Division
SELECT a.name
FROM parent a
INNER JOIN rel b
ON a.parent_ID = b.parent_ID
WHERE b.prop_id IN (1,5)
GROUP BY a.name
HAVING COUNT(*) = 2
UPDATE 1
if unique constraint was not enforce on prop_id
for every parent_id
, DISTINCT
is needed on this case.
SELECT a.name
FROM parent a
INNER JOIN rel b
ON a.parent_ID = b.parent_ID
WHERE b.prop_id IN (1,5)
GROUP BY a.name
HAVING COUNT(DISTINCT b.prop_id) = 2
I just saw this solution to a different question that seems to fit this case:
SELECT distinct parent_id
FROM rel as T1
INNER JOIN rel as T2
ON T1.parent_id = T2.parent_id
WHERE T1.prop_id = '1' and T2.prop_id = '5'
I've written your table in to a CTE, let me know if you require assistance in adapting the code for your purposes.
;WITH MyTable AS
(
SELECT parent_id = 1
,prop_id = 5 UNION ALL
SELECT 1,1 UNION ALL
SELECT 2,5 UNION ALL
SELECT 2,4 UNION ALL
SELECT 2,1 UNION ALL
SELECT 3,1 UNION ALL
SELECT 3,3
)
,Eval AS
(
SELECT parent_id
,PropEval = SUM(CASE WHEN prop_id IN (1,5) THEN 1 ELSE 0 END)
FROM MyTable
GROUP BY parent_id
)
SELECT parent_id
FROM Eval
WHERE PropEval = 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With