这两个查询似乎返回相同的结果。这是巧合还是真的一样?
1
SELECT t.ItemNumber,
(SELECT TOP 1 ItemDescription
FROM Transactions
WHERE ItemNumber = t.ItemNumber
ORDER BY DateCreated DESC) AS ItemDescription
FROM Transactions t
GROUP BY t.ItemNumber
2
SELECT DISTINCT(t.ItemNumber),
(SELECT TOP 1 ItemDescription
FROM Transactions
WHERE ItemNumber = t.ItemNumber
ORDER BY DateCreated DESC) AS ItemDescription
FROM Transactions t
一点解释: 我正试图从一个充满交易的表中获得一个独特的项目列表。对于每个项目,我正在寻找ItemNumber(标识字段)和最新的ItemDescription。
答案 0 :(得分:5)
你的例子#2让我挠了一会儿 - 我心里想:“你不能DISTINCT
一栏,这意味着什么?” - 直到我意识到发生了什么。
当你有
时SELECT DISTINCT(t.ItemNumber)
你不,尽管出现了,但实际上要求t.ItemNumber
的不同值!您的示例#2实际上被解析为与
SELECT DISTINCT
(t.ItemNumber)
,
(SELECT TOP 1 ItemDescription
FROM Transactions
WHERE ItemNumber = t.ItemNumber
ORDER BY DateCreated DESC) AS ItemDescription
FROM Transactions t
在t.ItemNumber
周围使用语法正确但多余的括号。 <{1}}适用于整个结果集。
在这种情况下,由于您的DISTINCT
组按实际不同的列进行,因此您会得到相同的结果。我实际上有点惊讶的是SQL Server没有(在GROUP BY
示例中)坚持在GROUP BY
列表中提到了subqueried列。
答案 1 :(得分:4)
相同的结果,但第二个似乎有一个更昂贵的排序步骤,以在我的快速测试中应用DISTINCT
。
ROW_NUMBER
虽然......
with T as
(
SELECT ItemNumber,
ItemDescription,
ROW_NUMBER() OVER ( PARTITION BY ItemNumber ORDER BY DateCreated DESC) AS RN
FROM Transactions
)
SELECT * FROM T
WHERE RN=1
修改 ...而我的测试设置又被Joe's solution重击。
Plans http://img842.imageshack.us/img842/4105/executionplan.png
测试设置
CREATE TABLE Transactions
(
ItemNumber INT not null,
ItemDescription VARCHAR(50) not null,
DateCreated DATETIME not null
)
INSERT INTO Transactions
SELECT
number, NEWID(),DATEADD(day, cast(rand(CAST(newid() as varbinary))*10000
as int),getdate())
FROM master.dbo.spt_values
ALTER TABLE dbo.Transactions ADD CONSTRAINT
PK_Transactions PRIMARY KEY CLUSTERED
(ItemNumber,DateCreated)
答案 2 :(得分:3)
如果你至少跑了2005并且可以使用CTE,那么恕我直言就更清洁。
编辑:正如Martin's answer所指出的,这也表现得更好。
;with cteMaxDate as (
select t.ItemNumber, max(DateCreated) as MaxDate
from Transactions t
group by t.ItemNumber
)
SELECT t.ItemNumber, t.ItemDescription
FROM cteMaxDate md
inner join Transactions t
on md.ItemNumber = t.ItemNumber
and md.MaxDate = t.DateCreated
答案 3 :(得分:3)
基于数据&amp;简单的查询,都会返回相同的结果。但是,基本操作是非常不同的。
DISTINCT
,正如AakashM击败我指出的那样,应用于 所有 列值,包括来自子选择和计算列的值。 所有DISTINCT
所做的就是根据所涉及的所有列,从可见性 中删除重复项。这就是为什么它通常被认为是黑客攻击的原因,因为人们会使用它来摆脱重复,而不理解为什么查询首先返回它们(因为它们应该使用IN
或EXISTS
而不是通常是一个连接。 PostgreSQL是我所知道的唯一一个带有DISTINCT ON
子句的数据库,它可以像OP那样工作。
GROUP BY
子句不同 - 它主要用于分组以准确使用聚合函数。要为该功能提供服务,列值将是基于GROUP BY子句中定义的值的唯一值。此查询永远不需要DISTINCT,因为感兴趣的值已经是唯一的。
这是一个糟糕的例子,因为它将DISTINCT和GROUP BY描述为等于它们不等。
答案 4 :(得分:2)
是的,他们会返回相同的结果。
答案 5 :(得分:2)
由于您没有使用任何聚合函数,因此SQL Server应该足够聪明,可以将GROUP BY
视为DISTINCT
。
您可能还有兴趣查看以下Stack Overflow帖子,以便进一步阅读此主题:
答案 6 :(得分:1)
GROUP BY
才能正确返回结果。由于您没有使用聚合函数,因此不需要GROUP BY
,因此查询是相同的。
答案 7 :(得分:1)
是的,他们会返回相同的结果。
通常,group by子句(找到here)按照提到的特定列对行进行分组,如果你在select语句中有一个总和。因此,如果你有一个像这样的表:
O_Id OrderDate OrderPrice Customer
1 2008/11/12 1000 Hansen
2 2008/10/23 1600 Nilsen
3 2008/09/02 700 Hansen
4 2008/09/03 300 Hansen
5 2008/08/30 2000 Jensen
6 2008/10/04 100 Nilsen
如果您按客户分组并要求获得金额或订单价格
Customer SUM(OrderPrice)
Hansen 2000
Nilsen 1700
Jensen 2000
与此相反,distinct(找到here)只是使它没有重复的行。在这种情况下,原始表将保持不变,因为每一行都与其他行不同。