注意:我已经简化了问题,因为我认为这个问题和答案都比预期更复杂。
我想要一个反连接,其条件不是第一个表中不存在。
A"正常"反加入将找出未通过
订购的产品Select Products from `Product / Manufacturer` as T1
Left Join `Customer / Product` as T2
On T2.Zip is NULL
然而,我所寻找的是哪些客户并没有订购哪些产品,实质上是:
Select Products from `Product / Manufacturer`
where Manufacturer = 'Acme' that do not exist in `Customer / Product`
where Customer = 'Karen'
和
Select Products from `Product / Manufacturer`
where Manufacturer = 'Exxon' that do not exist in `Customer / Product`
where Customer = 'Karen'
和
Select Products from `Product / Manufacturer`
where Manufacturer = 'Acme' that do not exist in `Customer / Product`
where Customer = 'Bob'
和
Select Products from `Product / Manufacturer`
where Manufacturer = 'Exxon' that do not exist in `Customer / Product`
where Customer = 'Bob'
' 但作为一个查询,因为有100个"客户"和100多家制造商。
答案 0 :(得分:1)
如果您想排除制造商的所有产品,而该制造商的产品不会以任何顺序出现......
那意味着您只想包含仅来自某些制造商的产品......
哪些制造商的产品出现在订单中?
SELECT r.manufacturer
FROM products r
JOIN orders s
ON s.product = r.product
GROUP BY r.manufacturer
您可以将该查询包装在parens中并将其包含为内联视图...
SELECT p.*
FROM ( SELECT r.manufacturer
FROM product r
JOIN orders s
ON s.product = r.product
GROUP BY r.manufacturer
) q
JOIN product p
ON p.manufacturer = q.manufacturer
LEFT
JOIN orders o
ON o.product = p.Product
WHERE o.product IS NULL
还有其他查询模式会返回相同的结果。
<强>后续强>
注意:原始规范中未明确“按性别/小时划分”部分。
查询模式非常相似。使用内联视图查询为每个性别/小时返回不同的制造商列表。
然后将该集合加入产品表,以获取这些制造商的每个产品。这将包括订购的产品,以及未订购的产品。
然后应用反连接模式,以排除按性别/小时排序的产品。
SELECT q.gender
, q.hour
, p.manufacturer
, p.product
FROM ( SELECT s.gender
, s.hour
, r.manufacturer
FROM orders s
JOIN product r
ON r.product = s.product
GROUP
BY s.gender
, s.hour
, r.manufacturer
) q
JOIN product p
ON p.manufacturer = q.manufacturer
LEFT
JOIN orders o
ON o.gender = q.gender
AND o.hour = q.hour
AND o.product = p.product
WHERE o.product IS NULL
如果不清楚,请考虑以下查询返回等效集。内联线视图查询t
按性别/小时返回制造商的所有产品集。
由于附加的内联视图,此查询效率较低(至少在MySQL中)。虽然时间更长,但可能更容易理解,因为视图查询t
明确表示可以返回的所有可能行的集合...按制造商/性别/小时的每个产品。 (要查看该集,可以拉出视图查询t
并单独运行以查看它返回的内容。)
在最外面的查询中,t
被引用,就像它是一个表一样。如果t
被简单的表引用替换,则查询将只是一个简单的反连接。 t
中的所有行,不包括匹配的行。
SELECT t.gender
, t.hour
, t.manufacturer
, t.product
FROM (
SELECT q.gender
, q.hour
, q.manufacturer
, p.product
FROM ( SELECT s.gender
, s.hour
, r.manufacturer
FROM orders s
JOIN product r
ON r.product = s.product
GROUP
BY s.gender
, s.hour
, r.manufacturer
) q
JOIN product p
ON p.manufacturer = q.manufacturer
) t
LEFT
JOIN orders o
ON o.gender = t.gender
AND o.hour = t.hour
AND o.product = t.product
WHERE o.product IS NULL
我建议您先获取返回的行集。在您添加GROUP BY
和GROUP_CONCAT
聚合以折叠行之前。
如果要将“hour”的多个值组合为“am”或“pm”,则可以使用返回“am”或“pm”的表达式(代替“hour”)。 (考虑到该表达式是表中的另一列;但不是引用表中的列,而是使用从表中的其他列派生值的表达式。
IF(x.hour<12,'am','pm')