2

如果我有一个表 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 年 2 月 11 日相比,我如何检索 2013 年 2 月 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

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'
                  )

两者都返回空集。

我设法让它工作的唯一方法是使用临时表;

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

临时表是不可能的。在不使用临时表的情况下如何实现这一点?

非常感谢,

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

4

4 回答 4

4
SELECT  a.*
FROM
        (
            SELECT  item, size
            FROM    tableName
            WHERE   date = '2013-02-11'
        ) a
        LEFT JOIN
        (
            SELECT  item, size
            FROM    tableName
            WHERE   date = '2013-02-13'
        ) b ON  a.item = b.item AND
                a.size = b.size
WHERE b.size IS NULL
于 2013-02-23T14:16:59.487 回答
1

使用聚合查询:

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

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

于 2013-02-23T15:57:53.840 回答
0

你也可以试试这个简单的查询

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'
于 2013-02-23T14:31:13.757 回答
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为 NULL 的行,这意味着该tb实例与该实例不匹配ta并且 tb.date是一个特定值。现在,如果 中没有匹配项,则它的tb所有列都将返回为 NULL,其中包括tb.date,这意味着它不能等于一个值并且同时为空。

显然,你的意图不同。您想将一个表的一个子集左连接到另一个子集(同一个表的,就像它发生的那样)。在这种情况下,应将定义您要加入的子集的条件放入 ON 子句中。也就是说,您不是在两个实例的两个itemsize列都匹配的唯一条件下加入,而是在这些列匹配并且另一个实例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

另一个查询

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'
                  )

似乎是混淆的EXISTS结果IN

首先,EXISTS 是如何工作的。它true在其子查询返回非空行集时返回。哪些列无关紧要,只有行的存在才重要。如果没有返回,则结果为false。这样,您的查询如下所示:

返回date'2013-02-11'AND 没有任何行的每一行date = '2013-02-11'

虽然您可能打算通过该查询说如下内容:

返回其date'2013-02-11'AND 的每一行,其中没有与和相同对应行。 itemsizedate'2013-02-11'

也就是说,您需要将 EXISTS 子查询与主查询相关联,这意味着将当前行的size包含item到 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
                  )

另一方面,您可以重写相同的查询以使用NOT IN而不是NOT EXISTS. 这里:

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'
                           )

基本上说:

返回其(item, size)对 fordate = '2013-02-11'不在 for 的(item, size)对集合中的每一行date = '2013-02-11'

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

于 2013-02-23T17:39:20.467 回答