我有两个表产品和多个关系的部分和一个连接表products_sections.产品可以是一个或多个部分(新的,汽车的,飞机的,旧的).
Products
id name
-----------------
1 something
2 something_else
3 other_thing
Sections
id name
-----------------
1 new
2 car
Products_sections
product_id section_id
--------------------------
1 1
1 2
2 1
3 2
Run Code Online (Sandbox Code Playgroud)
我想提取新车和汽车部分的所有产品.在此示例中,返回的结果应该是产品1.获取此信息的正确mysql查询是什么?
SELECT Products.name
FROM Products
WHERE NOT EXISTS (
SELECT id
FROM Sections
WHERE name IN ('new','car')
AND NOT EXISTS (
SELECT *
FROM Products_sections
WHERE Products_sections.section_id = Sections.id
AND Products_sections.product_id = Products.id
)
)
Run Code Online (Sandbox Code Playgroud)
换句话说,选择那些产品的Products_sections表中没有缺少所需的Section.id值的产品.
回答andho的评论:
你可以放
NOT EXISTS (<select query>)
Run Code Online (Sandbox Code Playgroud)
像任何其他谓词一样进入WHERE子句.如果<select query>描述的结果集中没有行,它将评估为TRUE.
逐步地,这里是如何得到这个查询作为答案:
步骤1.要求是识别"在'新'和'汽车'部分中的所有产品".
步骤2.如果"新"和"汽车"部分都包含产品,则产品在"新"和"汽车"部分.同样地,如果这些部分都不能包含产品,则产品同时位于"新"和"汽车"部分.(注意双重否定:既 不能包含.)再次重申,我们希望所有没有必需部分的产品不能包含产品.
所需的部分是这些:
SELECT id
FROM Sections
WHERE name IN ('new','car')
Run Code Online (Sandbox Code Playgroud)
因此,所需的产品是:
SELECT Products.name
FROM Products
WHERE NOT EXISTS ( -- there does not exist
SELECT id -- a section
FROM Sections
WHERE name IN ('new','car') -- that is required
AND (the section identified by Sections.id fails to contain the product identified by Products.id)
)
Run Code Online (Sandbox Code Playgroud)
步骤3.如果给定部分和特定产品的Products_sections中有一行,则给定部分(例如"new"或"car")确实包含特定产品.因此,如果Products_sections中没有这样的行,则给定的部分不能包含特定的产品.
步骤4.如果下面的查询确实包含一行,则section_id部分确实包含product_id产品:
SELECT *
FROM Products_sections
WHERE Products_sections.section_id = Sections.id
AND Products_sections.product_id = Products_id
Run Code Online (Sandbox Code Playgroud)
因此,如果上面的查询在结果中没有产生行,或者如果不是EXISTS(),则section_id部分无法包含产品(这就是我们需要表达的内容).
看起来很复杂,但是一旦你掌握了它,它就会坚持:是否所有必需的物品都存在?是的,只要不存在不存在的必需项目.