Mysql 选择在一个日期出现但不在另一个日期出现的记录?
如果我有一个表t1,它看起来是这样的,其中记录在项目、大小和日期的组合上是唯一的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
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'
)