首页 > 解决方案 > Group BY 语句错误以获取唯一记录

问题描述

我是 SQL Server 的新手,曾经使用 MYSQL 并尝试使用 Group By 从表中获取记录。

表结构如下:

SELECT S1.ID,S1.Template_ID,S1.Assigned_By,S1.Assignees,S1.Active FROM "Schedule" AS S1;

输出:

ID Template_ID  Assigned_By Assignees Active
2   25          1           3         1
3   25          5           6         1
6   26          5           6         1

我需要使用下面的 Group By 语句获取所有列的值

SELECT Template_ID FROM "Schedule" WHERE "Assignees" IN(6, 3) GROUP BY "Template_ID";

输出:

Template_ID

25
26

我尝试使用以下代码使用 Group By 获取表,但它正在获取所有行。

SELECT S1.ID,S1.Template_ID,S1.Assigned_By,S1.Assignees,S1.Active FROM "Schedule" AS S1 INNER JOIN(SELECT Template_ID FROM "Schedule" WHERE "Assignees" IN(6, 3) GROUP BY "Template_ID") AS S2 ON S2.Template_ID=S1.Template_ID

我的输出应该是,

   ID Template_ID  Assigned_By Assignees Active
    2   25          1           3         1
    6   26          5           6         1

我想知道我是否也可以获得列的 ID?我使用 ID 来编辑网络中的记录。

标签: sqlsql-servergroup-by

解决方案


该查询在 MySQL 中也不能按预期工作,除非是偶然的。

MySQL 中的非聚合列不是 SQL 标准的一部分,甚至在 MySQL 5.7 及更高版本中也不允许,ONLY_FULL_GROUP_BY除非更改模式的默认值。

在早期版本中,结果是不确定的

服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。此外,从每个组中选择值不会受到添加 ORDER BY 子句的影响。

这意味着无法知道此查询将返回哪些行:

SELECT S1.ID,S1.Template_ID,S1.Assigned_By,S1.Assignees,S1.Active 
FROM "Schedule" AS S1
GROUP BY Template_ID;

要获得确定性结果,您需要一种使用MySQL 8 中引入的排名函数ROW_NUMBER()对行进行排名的方法,例如. 至少自 SQL Server 2012 起,这些在 SQL Server 中已经可用。两个数据库的语法相同:

WITH ranked as AS 
(
    SELECT 
        ID,Template_ID,Assigned_By,Assignees Active, 
        ROW_NUMBER(PARTITION BY Template_ID Order BY ID)
    FROM Scheduled
    WHERE Assignees IN(6, 3) 
)
SELECT ID,Template_ID,Assigned_By,Assignees Active
FROM ranked
Where RN=1

PARTITION BY Template_ID根据结果​​行的Template_ID值将结果行拆分为单独的分区。在该分区中,行根据ORDER BY子句进行排序。最后,ROW_NUMBER计算每个有序分区行的行号。


推荐阅读