Sql 这两个查询是相同的-分组方式还是不同的?
这两个查询似乎返回相同的结果。这是巧合还是真的一样 一, 二, 一点解释:Sql 这两个查询是相同的-分组方式还是不同的?,sql,sql-server,sql-server-2008,group-by,Sql,Sql Server,Sql Server 2008,Group By,这两个查询似乎返回相同的结果。这是巧合还是真的一样 一, 二, 一点解释: 我试图从一个充满事务的表中获得一个不同的项目列表。对于每个项目,我都会在标识字段中查找ItemNumber和最近的ItemDescription。是,它们将返回相同的结果 因为您没有使用任何聚合函数,SQL Server应该足够聪明,可以将GROUP BY作为一个独立的函数来处理 您可能还对查看以下堆栈溢出帖子感兴趣,以便进一步阅读本主题: 在sql查询中使用聚合函数时,需要使用GROUP BY来正确返回结果。由于不使用
我试图从一个充满事务的表中获得一个不同的项目列表。对于每个项目,我都会在标识字段中查找ItemNumber和最近的ItemDescription。是,它们将返回相同的结果 因为您没有使用任何聚合函数,SQL Server应该足够聪明,可以将GROUP BY作为一个独立的函数来处理 您可能还对查看以下堆栈溢出帖子感兴趣,以便进一步阅读本主题:
在sql查询中使用聚合函数时,需要使用GROUP BY来正确返回结果。由于不使用聚合函数,因此不需要GROUP BY,因此查询是相同的。是,它们返回相同的结果 通常情况下,GROUPBY子句按所提到的特定列对行进行分组,因此,如果select语句中有一个sum。因此,如果您有一个表,如:
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 found只会使它成为一个不重复的行。在这种情况下,原始表将保持不变,因为每一行都不同于其他行。如果您至少运行了2005年,并且可以使用,这将稍微干净一些 编辑:正如中所指出的,这也表现得更好
;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
你的例子2让我挠头了一段时间——我想:你不能区分一个列,这意味着什么直到我意识到发生了什么 当你有
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周围使用语法正确但多余的括号。DISTINCT应用于整个结果集
在这种情况下,由于按列分组实际上是不同的,因此得到的结果是相同的。实际上,我有点惊讶,SQL Server在GROUP BY示例中没有坚持在GROUP BY列表中提到子查询列。相同的结果,但第二个结果似乎有一个更昂贵的排序步骤,以便在我的快速测试中应用DISTINCT 但两人都被排在了视线之外
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
编辑…然后在我的测试设置中被重击
测试设置
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)
基于数据和简单查询,两者将返回相同的结果。然而,基本操作是非常不同的 正如AakashM告诉我的那样,DISTINCT应用于所有列值,包括来自子选择和计算列的值。DISTINCT所做的全部工作是根据涉及的所有列从可见性中删除重复项。这就是为什么它通常被认为是一种黑客行为,因为人们会使用它来消除重复项,而不理解为什么查询首先返回它们,因为它们通常应该在或存在中使用,而不是连接。据我所知,PostgreSQL是唯一一个具有DISTINCT ON子句的数据库,它确实按照OP的预期工作 GROUPBY子句是不同的-它的主要用途是分组,以便准确地使用聚合函数。为了服务于该函数,列值将是基于GROUPBY子句中定义的唯一值。此查询永远不需要使用DISTINCT,因为感兴趣的值已经是唯一的 结论
这是一个糟糕的示例,因为它将DISTINCT和GROUP BY描述为相等,而实际情况并非如此。sql server难道没有某种解释分析来告诉您它真正在做什么吗?而且我觉得这有点巧合。。。虽然我认为group by可能意味着不同的或类似的……但估计的执行计划并不相同。第一个查询更快。谢谢,我不知道CTEs。我正在使用SQL Server 2008。+1个漂亮的捕获!顺便说一句,这解释了为什么第二个查询有一个更昂贵的执行计划,正如其他答案所指出的。这实际上是几天前SQLServerCentral.com上的一个问题。PostgreSQL是我遇到的唯一一个语法不同的数据库,允许您为特定列获取不同的值。我使用max/group by的CTE版本生成了与您的行号版本几乎相同的执行计划。@Joe-对我来说,您的版本又好了很多。我会重新更新!
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
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)