Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 这两个查询是相同的-分组方式还是不同的?_Sql_Sql Server_Sql Server 2008_Group By - Fatal编程技术网

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)