为什么这两个 'EXISTS' 的查询表现不同?
Why do these two queries with 'EXISTS' behave differently?
有两个table。 Customers
,custid
作为主键,Orders
,custid
作为主键。
Customers
table 有列 custid
、companyname
Orders
table 有列 custid
、orderid
、orderdate
我想 return 在 2007 年而不是在“2008 年”下订单的客户。我想returncustid
和companyname
在最后的结果。
我有 query1 总共有 7 个不同的 custid
来获取正确的结果
我有 query2,它给了我更多不同的行,即最终结果中的 86 行
查询1
SELECT custid, companyname
FROM customers c
WHER EXISTS
(SELECT custid
FROM orders o
WHERE YEAR(orderdate) = '2007'AND o.custid = c.custid)
AND NOT EXISTS
(SELECT custid
FROM orders o
WHERE YEAR(orderdate) = '2008'AND o.custid=c.custid)
查询2
SELECT DISTINCT custid, companyname
FROM customers c
WHERE EXISTS
(SELECT custid
FROM orders o
WHERE YEAR(orderdate) = '2007'
AND YEAR(orderdate) <> '2008'
AND o.custid=c.custid)
我不明白 query2 的问题以及为什么它不能给出正确的结果?
正确的查询是第一个。
如 user2722968 所述,使用:
WHERE YEAR(orderdate) = '2007' AND YEAR(orderdate) <> '2008'
作品 per-row。所以,如果一个 custid 在 2007 年和 2008 年都有一个 orderid,
前面提到的 WHERE
确实 return 2007 行,因为它确实 YEAR(orderdate) = '2007' AND YEAR(orderdate) <> '2008'
.
相反,(NOT) EXISTS
中的不同代码不是对行执行操作 (semijoi),而是对 result-sets。这就是你需要的。
一个建议:如果可以避免的话,最好不要使用函数,因为当你对一个字段应用函数时,如果它上面有索引,它就不能用来加速计算。因此,最好使用:
而不是 YEAR(orderdate)=2007
orderdate>='20070101' and orderdate<'20080101'
考虑到这一点,查询变为:
SELECT custid, companyname
FROM customers c
WHERE EXISTS
(SELECT custid
FROM orders o
WHERE orderdate>='20070101' and orderdate<'20080101' AND o.custid = c.custid)
AND NOT EXISTS
(SELECT custid
FROM orders o
WHERE orderdate>='20080101' and orderdate<'20090101' AND o.custid=c.custid)
Why do these two queries with 'EXISTS' behave differently?
因为:
- 如果客户在 2007 年有订单并且在 2008 年没有(不同的)订单,则第一个查询将 return 客户。
- 但是第二个查询将 return 一个客户,如果它在 2007 年有订单但同一个订单不在 2008 年(并且由于订单已经在 2007 年,那么它不在 2008 年,所以条件
<> 2008
是多余的)。
看起来第一个查询更有意义。
好的,让我们有一个客户(客户 1)和以下 orders
table
customers
table
custid orderid orderdate
---------------------------
1 1 1.1.2007
1 2 1.1.2008
您的第二个查询解释了客户的子查询
SELECT custid
FROM orders o
WHERE YEAR(orderdate) = 2007 AND YEAR(orderdate) <> 2008 AND o.custid = 1
它 returns 第一行。因此,对于客户,exists
被评估为 true
,因为有一行 year(orderdate) = 2007 and year(orderdate) <> 2008
(第一行)。但是,这并不意味着不存在与 2008 年不同的行!
很明显,第一个查询returns没有结果,因为客户1不满足not exists
谓词。如果我们用关系代数表达第一个查询,那么它对应于两个集合之间的差异,然而,第二个查询只是一个带有条件的普通连接。
有一种更简单的方法可以解决这个问题 EXCEPT
select c.custid, c.companyname
from Customers c
join
Orders o
on o.custid=c.custid
where orderdate>='20070101' and orderdate<'20080101'
except
select c.custid, c.companyname
from [TSQL2012].Sales.Customers c
join
[TSQL2012].Sales.Orders o
on o.custid=c.custid
where orderdate>='20080101' and orderdate<'20090101'
有两个table。 Customers
,custid
作为主键,Orders
,custid
作为主键。
Customers
table 有列 custid
、companyname
Orders
table 有列 custid
、orderid
、orderdate
我想 return 在 2007 年而不是在“2008 年”下订单的客户。我想returncustid
和companyname
在最后的结果。
我有 query1 总共有 7 个不同的 custid
来获取正确的结果
我有 query2,它给了我更多不同的行,即最终结果中的 86 行
查询1
SELECT custid, companyname
FROM customers c
WHER EXISTS
(SELECT custid
FROM orders o
WHERE YEAR(orderdate) = '2007'AND o.custid = c.custid)
AND NOT EXISTS
(SELECT custid
FROM orders o
WHERE YEAR(orderdate) = '2008'AND o.custid=c.custid)
查询2
SELECT DISTINCT custid, companyname
FROM customers c
WHERE EXISTS
(SELECT custid
FROM orders o
WHERE YEAR(orderdate) = '2007'
AND YEAR(orderdate) <> '2008'
AND o.custid=c.custid)
我不明白 query2 的问题以及为什么它不能给出正确的结果?
正确的查询是第一个。
如 user2722968 所述,使用:
WHERE YEAR(orderdate) = '2007' AND YEAR(orderdate) <> '2008'
作品 per-row。所以,如果一个 custid 在 2007 年和 2008 年都有一个 orderid,
前面提到的 WHERE
确实 return 2007 行,因为它确实 YEAR(orderdate) = '2007' AND YEAR(orderdate) <> '2008'
.
相反,(NOT) EXISTS
中的不同代码不是对行执行操作 (semijoi),而是对 result-sets。这就是你需要的。
一个建议:如果可以避免的话,最好不要使用函数,因为当你对一个字段应用函数时,如果它上面有索引,它就不能用来加速计算。因此,最好使用:
而不是 YEAR(orderdate)=2007orderdate>='20070101' and orderdate<'20080101'
考虑到这一点,查询变为:
SELECT custid, companyname
FROM customers c
WHERE EXISTS
(SELECT custid
FROM orders o
WHERE orderdate>='20070101' and orderdate<'20080101' AND o.custid = c.custid)
AND NOT EXISTS
(SELECT custid
FROM orders o
WHERE orderdate>='20080101' and orderdate<'20090101' AND o.custid=c.custid)
Why do these two queries with 'EXISTS' behave differently?
因为:
- 如果客户在 2007 年有订单并且在 2008 年没有(不同的)订单,则第一个查询将 return 客户。
- 但是第二个查询将 return 一个客户,如果它在 2007 年有订单但同一个订单不在 2008 年(并且由于订单已经在 2007 年,那么它不在 2008 年,所以条件
<> 2008
是多余的)。
看起来第一个查询更有意义。
好的,让我们有一个客户(客户 1)和以下 orders
table
customers
table
custid orderid orderdate
---------------------------
1 1 1.1.2007
1 2 1.1.2008
您的第二个查询解释了客户的子查询
SELECT custid
FROM orders o
WHERE YEAR(orderdate) = 2007 AND YEAR(orderdate) <> 2008 AND o.custid = 1
它 returns 第一行。因此,对于客户,exists
被评估为 true
,因为有一行 year(orderdate) = 2007 and year(orderdate) <> 2008
(第一行)。但是,这并不意味着不存在与 2008 年不同的行!
很明显,第一个查询returns没有结果,因为客户1不满足not exists
谓词。如果我们用关系代数表达第一个查询,那么它对应于两个集合之间的差异,然而,第二个查询只是一个带有条件的普通连接。
有一种更简单的方法可以解决这个问题 EXCEPT
select c.custid, c.companyname
from Customers c
join
Orders o
on o.custid=c.custid
where orderdate>='20070101' and orderdate<'20080101'
except
select c.custid, c.companyname
from [TSQL2012].Sales.Customers c
join
[TSQL2012].Sales.Orders o
on o.custid=c.custid
where orderdate>='20080101' and orderdate<'20090101'