Mysql 反加入组/条件

Mysql 反加入组/条件,mysql,left-join,Mysql,Left Join,注:我简化了问题,因为我认为问题和答案都比预期的复杂 我想创建一个反连接,该反连接的条件不是第一个表中不存在的条件 表产品/制造商 小部件/顶点 桨/顶点 球/顶点 天然气/埃克森美孚 泵/埃克森美孚 表:客户/产品 凯伦/鲍尔 摇动/划桨 凯伦/煤气 摆锤/泵 “正常”反连接将发现哪些产品未通过订购 Select Products from `Product / Manufacturer` as T1 Left Join `Customer / Product` as T2 On T

注:我简化了问题,因为我认为问题和答案都比预期的复杂

我想创建一个反连接,该反连接的条件不是第一个表中不存在的条件

表产品/制造商
  • 小部件/顶点
  • 桨/顶点
  • 球/顶点
  • 天然气/埃克森美孚
  • 泵/埃克森美孚
表:客户/产品
  • 凯伦/鲍尔
  • 摇动/划桨
  • 凯伦/煤气
  • 摆锤/泵
“正常”反连接将发现哪些产品未通过订购

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'

" 但作为一个查询,因为有100多个“客户”和100多个制造商。

如果要排除某个制造商的所有产品,而该制造商的任何产品都不会以任何顺序出现

那就意味着你只想包括某些制造商的产品

哪些制造商的产品出现在订单中

SELECT r.manufacturer 
  FROM products r
  JOIN orders s
    ON s.product = r.product
 GROUP BY r.manufacturer 
您可以将该查询包装在参数中,并将其作为内联视图包含

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
然后将该集合连接到product表,以从这些制造商处获得每个产品。这将包括订购的产品以及未订购的产品

然后应用反连接模式,以排除按性别/小时订购的产品

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
按性别/小时返回制造商提供的所有产品集

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
由于额外的内联视图,此查询的效率稍低(至少在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

我建议您首先返回一组行。在添加
groupby
groupconcat
聚合以折叠行之前

如果要将多个“hour”值分组为“am”或“pm”,可以使用返回“am”或“pm”的表达式(代替“hour”)。(请考虑该表达式是表中的另一列;但您使用的表达式不是引用表中的列,而是从表中的其他列派生值

   IF(x.hour<12,'am','pm')

IF(x.hourp请添加此给定数据集的预期输出。您是否可以共享预期输出。@1000111我在这里更新了小提琴@Sang我在这里更新了小提琴我正在尝试获取所有未订购的产品,只有当该Mfctr订购了其他产品时。我已更新了小提琴,但想法是从麦当劳I订购的n AM McMuffins我想要一份男性在AM中没有从麦当劳订购的产品的清单。如果他们没有从BK订购,我不需要这份清单。如果女性在午餐时从汉堡王薯条订购,我需要一份他们没有订购的BK产品的清单。目前正在进行分组,但核心问题是我需要一份不是由制造商订购的产品的清单只有当其他产品从同一家公司订购时,我才在原始答案的基础上添加了后续内容,并给出了一个带有“按性别/小时分类”的示例查询。(在最初提出的问题中,规范的这一部分是不明确的,因为没有提及。我认为这就是查询预期输出的示例有助于澄清规范的地方。)我按照我的想法修改了问题的布局(希望)虽然您的回答很详细,而且非常感谢,但对于我想要的内容来说,这可能有点过分了,因为我可能没有解释清楚,我希望这样做。@user3649739:问题的更新是一个改进。要使用反连接模式来获取您要查找的集合,您需要一个行源来返回不存在的行。我确信还有其他行r将返回指定结果集的查询模式。我答案中的示例确实使用了问题中所示的反连接模式。我从SQL FIDLE的更新中获得了“按性别/小时细分”部分(演示表中有性别和小时列)。同样的模式也可以应用于“客户名称”代替“性别”。
   IF(x.hour<12,'am','pm')