patternsqlMinor
Finding parent by set of children
Viewed 0 times
childrenparentsetfinding
Problem
Given a many-to-many relationship (
Update: assume the standard many-to-many ternary mapping.
product/component), I need to find a product (or all products) that are composed from the given set of components. I can't wrap my head around the SQL query for this. A general solution, but if there is anything particular to SQLServer, that will work too.Update: assume the standard many-to-many ternary mapping.
Solution
This is a case of "relational division". I tagged the question accordingly, you can find basic information in the tag info.
You did not provide details. Assuming a standard many-to-many (n:m) relationship between products and components which is implemented with a
This needs at least an index on
There are many other ways. The best query depends on your exact table definition and data distribution. We assembled an arsenal of queries under this related question on SO, for Postgres / MySQL, but the SQL is (mostly) the same:
The above query finds products that contain at least the components with
Again, there are various ways exclude products with additional components:
You did not provide details. Assuming a standard many-to-many (n:m) relationship between products and components which is implemented with a
product_component table, a basic solution could look like this:SELECT c1.product_id
FROM product_component c1
JOIN product_component c2 ON c2.product_id = c1.product_id
JOIN product_component c3 ON c3.product_id = c1.product_id
WHERE c1.component_id = 1
AND c2.component_id = 2
AND c3.component_id = 3;This needs at least an index on
product_id and on component_id to be fast, ideally on (component_id, product_id).There are many other ways. The best query depends on your exact table definition and data distribution. We assembled an arsenal of queries under this related question on SO, for Postgres / MySQL, but the SQL is (mostly) the same:
- How to filter SQL results in a has-many-through relation
The above query finds products that contain at least the components with
component_id 1, 2 and 3. To find products that consist of those components exactly (no others components):SELECT c1.product_id
FROM product_component c1
JOIN product_component c2 ON c2.product_id = c1.product_id
JOIN product_component c3 ON c3.product_id = c1.product_id
LEFT JOIN product_component c0
ON c0.product_id = c1.product_id
AND c0.component_id NOT IN (c1.component_id
, c2.component_id
, c3.component_id)
WHERE c1.component_id = 1
AND c2.component_id = 2
AND c3.component_id = 3
AND c0.component_id IS NULL -- no other componentAgain, there are various ways exclude products with additional components:
- Select rows which are not present in other table
Code Snippets
SELECT c1.product_id
FROM product_component c1
JOIN product_component c2 ON c2.product_id = c1.product_id
JOIN product_component c3 ON c3.product_id = c1.product_id
WHERE c1.component_id = 1
AND c2.component_id = 2
AND c3.component_id = 3;SELECT c1.product_id
FROM product_component c1
JOIN product_component c2 ON c2.product_id = c1.product_id
JOIN product_component c3 ON c3.product_id = c1.product_id
LEFT JOIN product_component c0
ON c0.product_id = c1.product_id
AND c0.component_id NOT IN (c1.component_id
, c2.component_id
, c3.component_id)
WHERE c1.component_id = 1
AND c2.component_id = 2
AND c3.component_id = 3
AND c0.component_id IS NULL -- no other componentContext
StackExchange Database Administrators Q#124394, answer score: 4
Revisions (0)
No revisions yet.