Mysql 选择在一个日期出现但不在另一个日期出现的记录?

Mysql 选择在一个日期出现但不在另一个日期出现的记录?,mysql,sql,join,Mysql,Sql,Join,如果我有一个表t1,它看起来是这样的,其中记录在项目、大小和日期的组合上是唯一的 item size date 1234 S 2013-02-11 1234 M 2013-02-11 1234 L 2013-02-11 9999 S 2013-02-11 9999 M 2013-02-11 9999 L 2013-02-11 1234 S 2013-02-13 1234 M 2013-02-13 1234

如果我有一个表t1,它看起来是这样的,其中记录在项目、大小和日期的组合上是唯一的

item    size    date
1234    S   2013-02-11
1234    M   2013-02-11
1234    L   2013-02-11
9999    S   2013-02-11
9999    M   2013-02-11
9999    L   2013-02-11
1234    S   2013-02-13
1234    M   2013-02-13
1234    L   2013-02-13
9999    S   2013-02-13
9999    M   2013-02-13
与2013-02-11相比,如何检索2013-02-13中缺少的项目和尺寸

我要找的回报是

item    size
9999    L
我试过了

SELECT ta.item, 
         ta.size
FROM t1 ta 
    LEFT JOIN t1 tb 
        ON ta.item = tb.item
            AND ta.size = tb.size
WHERE ta.date = '2013-02-11'
   AND tb.date = '2013-02-13'
   AND tb.size IS NULL

两者都返回空集

我唯一能做到这一点的方法就是使用临时表

CREATE temporary table temp1
SELECT * FROM t1 WHERE date = '2013-02-11';

CREATE temporary table temp2
SELECT * FROM t1 WHERE date = '2013-02-13';

SELECT temp1.item, temp1.size FROM temp1
   LEFT JOIN temp2 
        ON temp1.item = temp2.item AND temp1.size = temp2.size
WHERE temp2.size IS NULL
临时表格是不可能的。如何在不使用临时表的情况下实现这一点

非常感谢,

(请温柔一点,我才刚开始呢!)


    • 您也可以尝试这个简单的查询

      SELECT item, size FROM dbo.Table_1 WHERE date = '2013-02-11'
      EXCEPT
      SELECT item, size FROM dbo.Table_1 WHERE date = '2013-02-13'
      

      使用聚合查询:

      select item, size
      from t1
      group by item, size
      having sum(case when date = '2013-02-11' then 1 else 0 end) = 1 and
             sum(case when date = '2013-02-13' then 1 else 0 end) = 0
      
      这是“组中的组”查询的一个示例。通过改变
      having
      子句,您可以在想要满足的条件上有很大的灵活性。例如:

      having sum(case when date = '2013-02-11' then 1 else 0 end) = 0 or
             sum(case when date = '2013-02-13' then 1 else 0 end) = 0
      

      将返回数据中存在但在任何一天都丢失的组合。

      其他人为您提供了有效的解决方案,本文仅介绍您失败的尝试,解释丢失的内容以及如何修复

      这个问题

      SELECT ta.item, 
               ta.size
      FROM t1 ta 
          LEFT JOIN t1 tb 
              ON ta.item = tb.item
                  AND ta.size = tb.size
      WHERE ta.date = '2013-02-11'
         AND tb.date = '2013-02-13'
         AND tb.size IS NULL
      
      失败,因为WHERE子句中存在矛盾。查询试图查找
      tb.size
      为空的行,这意味着
      tb
      实例与
      ta
      实例不匹配,并且
      tb.date
      是一个特定值。现在,如果
      tb
      中没有匹配项,则其所有列都将返回为null,其中包括
      tb.date
      ,这意味着它不能等于一个值,同时也不能为null

      显然,你的意图不同。您希望将表的一个子集左键联接到另一个子集(即同一表的另一个子集)。在这种情况下,定义要加入的子集的条件应该放在ON子句中。也就是说,加入的唯一条件不是两个实例的
      item
      size
      列都匹配,而是这些列匹配且另一个实例的
      date
      为特定值的组合条件。因此,这是您应该拥有的:

      SELECT ta.item, 
               ta.size
      FROM t1 ta 
          LEFT JOIN t1 tb 
              ON ta.item = tb.item
                  AND ta.size = tb.size
                  AND tb.date = '2013-02-13'
      WHERE ta.date = '2013-02-11'
         AND tb.date = '2013-02-13'
         AND tb.size IS NULL
      
      似乎是将
      存在
      与中的
      混淆的结果

      首先,存在是如何运作的。当其子查询返回非空行集时,它返回
      true
      。哪列不重要,只有行的存在才重要。如果未返回任何值,则结果为
      false
      。这样,您的查询如下所示:

      返回
      日期为
      '2013-02-11'
      日期为'2013-02-11'
      的所有行

      虽然你可能想通过这个查询说这样的话:

      返回其
      日期为
      '2013-02-11'
      且没有具有相同
      项目和
      大小以及
      日期为
      '2013-02-11'
      的对应行的每一行

      也就是说,您需要将EXISTS子查询与主查询关联起来,这意味着将当前行的
      大小
      包含到EXISTS测试中。因此,修复程序可能是这样的:

      SELECT item, size 
      FROM t1 ta
      WHERE ta.date = '2013-02-11'
         AND NOT EXISTS (
                          SELECT item, size 
                          FROM t1 tb
                          WHERE tb.date = '2013-02-13'
                            AND ta.item = tb.item
                            AND ta.size = tb.size
                        )
      
      基本上是说:

      返回
      日期='2013-02-11'
      (项目,大小)
      对不在
      日期='2013-02-11'
      (项目,大小)
      对设置中的每一行


      /
      IN
      NOT IN
      查询中的
      通常看起来比它的
      EXISTS
      /
      NOT EXISTS
      对应项更清晰。这两种方法是否会导致相同的查询计划是另一回事,在决定使用哪种方法之前,您可能应该先进行测试(但这当然也适用于
      LEFT JOIN+WHERE is NULL
      方法)。

      不幸的是,MySQL不支持
      INTERSECT和EXCEPT
      运算符。嗨,Nitesh,我应该说我使用的是mySQL,谢谢。我支持你,但不需要子查询。将2/13置于打开位置;和WHERE.+1中的2/11,尽管如果您将分组前的行限制为WHERE date in('2013-02-11','2013-02-13')
      ,您可以简化这两种情况下的
      条件。@AndriyM。是的,对于这个问题,这是一个好主意。谢谢戈登,这很有魅力,尽管我不得不承认我不太明白怎么做-我会研究这个问题,因为额外的灵活性可能非常有用。谢谢安德烈。我曾希望有人能解释我错在哪里。非常感谢你的帖子。
      
      SELECT ta.item, 
               ta.size
      FROM t1 ta 
          LEFT JOIN t1 tb 
              ON ta.item = tb.item
                  AND ta.size = tb.size
                  AND tb.date = '2013-02-13'
      WHERE ta.date = '2013-02-11'
         AND tb.date = '2013-02-13'
         AND tb.size IS NULL
      
      SELECT item, size 
      FROM t1
      WHERE t1.date = '2013-02-11'
         AND NOT EXISTS (
                          SELECT item, size 
                          FROM t1
                          WHERE t1.date = '2013-02-13'
                        )
      
      SELECT item, size 
      FROM t1 ta
      WHERE ta.date = '2013-02-11'
         AND NOT EXISTS (
                          SELECT item, size 
                          FROM t1 tb
                          WHERE tb.date = '2013-02-13'
                            AND ta.item = tb.item
                            AND ta.size = tb.size
                        )
      
      SELECT item, size 
      FROM t1
      WHERE date = '2013-02-11'
         AND (item, size) NOT IN (
                                  SELECT item, size 
                                  FROM t1
                                  WHERE date = '2013-02-13'
                                 )