如果我有一个表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
和
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
临时表是不可能的。如何在不使用临时表的情况下实现这一目标?
非常感谢,
(请温柔,我刚开始!)
答案 0 :(得分: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
答案 1 :(得分: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
将返回数据中存在的组合,但在任何一天都会丢失。
答案 2 :(得分: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'
答案 3 :(得分: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子句中。也就是说,您没有加入两个实例的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
另一个查询
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'
并且<{1}}没有任何行的每一行。
虽然您可能想通过该查询说出类似的内容:
返回
date = '2013-02-11'
为date
并且相同行没有相同'2013-02-11'
和{{1}的每一行和}item
的{{1}}。
也就是说,您需要将EXISTS子查询与主查询相关联,这意味着将当前行的size
和date
包含在EXISTS测试中。所以,这就是修复可能的样子:
'2013-02-11'
另一方面,您可以重写相同的查询以使用size
而不是item
。这里:
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)
date = '2013-02-11'
对中的每一行。
(item, size)
/ date = '2013-02-11'
查询通常看起来比其IN
/ NOT IN
对象更清晰。这两个是否会导致相同的查询计划是另一回事,您应该在决定使用哪种方法之前进行测试(当然,这也适用于EXISTS
方法)。