我有两个表产品和多个关系的部分和一个连接表products_sections。产品可以是一个或多个部分(新的,汽车,飞机,旧)。</ p>
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
我想提取新车和汽车部分的所有产品。在此示例中,返回的结果应为product 1.获取此结果的正确mysql查询是什么?
答案 0 :(得分:6)
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
)
)
换句话说,选择那些产品的Products_sections表中没有缺少所需的Section.id值的产品。
回答andho的评论:
你可以把
NOT EXISTS (<select query>)
像任何其他谓词一样进入WHERE子句。如果&lt; select query&gt;描述的结果集中没有行,它将评估为TRUE。
逐步地,这里是如何将此查询作为答案:
步骤1.要求是识别“同时在'新'和'汽车'部分中的所有产品”。
步骤2.如果“新”和“汽车”部分都包含产品,则产品位于“新”和“汽车”部分。同样地,如果这些部分都不能包含产品,则产品同时位于“新”和“汽车”部分。 (请注意双重否定: 无法包含。)再次重申,我们希望所有产品都有否必需部分失败包含产品。
所需的部分是:
SELECT id
FROM Sections
WHERE name IN ('new','car')
因此,所需的产品是:
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)
)
步骤3.如果给定部分和特定产品的Products_sections中有一行,则给定部分(例如“新”或“汽车”)确实包含特定产品。因此,如果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
因此,如果上面的查询不在其结果中产生一行,或者如果上面的查询
看起来很复杂,但是一旦你掌握了它,它就会坚持:是否所有必需的物品都存在?是的,只要不存在不存在的必需项目。
答案 1 :(得分:2)
我总是这样做:
从您尝试获取的内容开始(products
),然后通过查找表(products_sections
)查看您尝试过滤的内容(sections
) 。通过这种方式,您可以在普通视图中查找您正在寻找的内容,而且您无需记住代理键(这是一件很棒的事情,而不是记忆)。
select distinct
p.name
from
products p
inner join products_sections ps on
p.product_id = ps.product_id
inner join sections s1 on
ps.section_id = s1.section_id
inner join sections s2 on
ps.section_id = s2.section_id
where
s1.name = 'new'
and s2.name = 'car'
瞧。三个inner join
,你有一个很好的,清晰的,简洁的查询,显而易见的是它带来了什么。希望这有帮助!
答案 2 :(得分:0)
SELECT product_id, count(*) AS TotalSection
FROM Products_sections
GROUP BY product_id
WHERE section_id IN (1,2)
HAVING TotalSection = 2;
看看这是否适用于mysql。
答案 3 :(得分:0)
下面的查询有点笨拙,但它应该回答你的问题:
select products.id
from products
where products.id in
(
select products_sections.product_id
from products_sections
where products_sections.section_id=1
)
and products.id in
(
select products_sections.product_id
from products_sections
where products_sections.section_id=2
)
答案 4 :(得分:0)
在两个连接表子集上自行连接,然后选择唯一的产品ID。
SELECT DISTINCT car.product_id
FROM ( SELECT product_id
FROM Product_sections
WHERE section_id = 2
) car JOIN
( SELECT product_id
FROM Product_sections
WHERE section_id = 1
) neww
ON (car.product_id = neww.product_id)
此查询是更一般解决方案的变体:
SELECT DISTINCT car.product_id
FROM product_sections car join
product_sections neww ON (car.product_id = neww.product_id AND
car.section_id = 2 AND
neww.section_id = 2)
效率较低但更直接的解决方案是:
SELECT p.name FROM Products p WHERE
EXISTS (SELECT 'found car'
FROM Products_sections ps
WHERE ps.product_id = p.id AND ps.section_id = 2)
AND
EXISTS (SELECT 'found new'
FROM products_sections ps
WHERE ps.product_id = p.id AND ps.section_id = 1)
为了清晰起见,我使用id进行操作。如有必要,请将表达式section_id = 2
和section_id = 1
替换为
section_id = (SELECT s.id FROM Sections s WHERE s.name = 'car')
section_id = (SELECT s.id FROM Sections s WHERE s.name = 'new')
此外,您可以通过插入上述任何查询来选择产品名称,如下所示:
SELECT Products.name FROM Products
WHERE EXISTS (
SELECT 'found product'
FROM product_sections car join
product_sections neww ON (car.product_id = neww.product_id AND
car.section_id = 2 AND
neww.section_id = 2)
WHERE car.product_id = Products.id
)
答案 5 :(得分:0)
SELECT p.*
FROM Products p
INNER JOIN (SELECT ps.product_id
FROM Products_sections ps
INNER JOIN Sections s
ON s.id = ps.section_id
WHERE s.name IN ("new","car")
GROUP BY ps.product_id
HAVING Count(ps.product_id) = 2) pp
ON p.id = pp.product_id
答案 6 :(得分:0)
当您需要搜索更多部分时,此查询将为您提供结果,而无需添加更多内部联接。这里会改变的是:
count的where子句中的值,应该替换为您要搜索的部分的数量
选择id
,name
FROM
(
SELECT
products
。id
,
products
。name
,
sections
。name
AS section_name
,
COUNT(*)AS count
FROM products
INNER JOIN products_sections
在products_sections
。product_id
= products
。id
INNER JOIN sections
在sections
。id
= products_sections
。section_id
在哪里sections
。name
IN('car','new')
GROUP BY products
。id
)AS P
在哪里count
= 2
答案 7 :(得分:0)
select
`p`.`id`,
`p`.`name`
from `Sections` as `s`
join `Products_sections` as `ps` on `ps`.`section_id` = `s`.`id`
join `Products` as `p` on `p`.`id` = `ps`.`product_id`
where `s`.`id` in ( 1,2 )
having count( distinct `s`.`name` = 2 )
将返回......
id name
-----------------
1 something
那是你在找什么?