SQL 服务器 STRING_AGG 功能排序未按预期工作
SQL Server STRING_AGG function sorting is not working as expected
为了在动态生成的数据集上重现这个问题,我已经崩溃了,但它终于成功了!
这是代码
;with tbl as
(
select Id, ClCode, Manager, ChangeDate
from (values
(1, '000005', 'Cierra Vega', '2017-10-05'),
(2, '000005', 'Alden Cantrell', '2017-11-29'),
(3, '000005', 'Alden Cantrell', '2017-11-30'),
(4, '000005', 'Kierra Gentry', '2018-09-05'),
(5, '000005', 'Kierra Gentry', '2018-09-12'),
(6, '000005', 'Pierre Cox', '2018-11-06'),
(7, '000005', 'Thomas Crane', '2019-09-11'),
(8, '000005', 'Thomas Crane', '2019-10-01'),
(9, '000005', 'Miranda Shaffer', '2020-04-27'),
(10,'000360', 'Bradyn Kramer', '2017-10-06')
) as t(Id, ClCode, Manager, ChangeDate)
)
, grouped as
(
select c.ClCode
, count(distinct c.Manager) [ManagerChangesCount]
, STRING_AGG(c.[Manager], ',') within group (order by c.MinChangeDate) [Managers]
, STRING_AGG(c.MinChangeDate, ',') within group (order by c.MinChangeDate) [ChangeDates]
from (
select x.ClCode
, x.[Manager]
, min(x.ChangeDate) [MinChangeDate]
from tbl x
group by x.ClCode, x.[Manager]
) c
group by c.ClCode
)
select *
from grouped
我的示例数据集包含有关某些客户 (ClCode) 何时 (ChangeDate) 更改其经理 (Manager) 的数据。它是真正的 DWH 客户维度 table(SCD 类型 2)的一部分,因此这些 "duplicates" 只包含其他列某处的更改。
我想要实现的目标:我需要一个客户代码列表,其中包含他们的经理更换了多少次,以及这些经理姓名的逗号分隔列表,这些名称按更改顺序从左到右排序
ClCode ManagerChangesCount Managers ChangeDates
000005 6 Cierra Vega,Alden Cantrell,Kierra Gentry,Pierre Cox,Thomas Crane,Miranda Shaffer 2017-10-05,2017-11-29,2018-09-05,2018-11-06,2019-09-11,2020-04-27
000360 1 Bradyn Kramer 2017-10-06
但事实上我收到的结果没有或有一些奇怪的排序
ClCode ManagerChangesCount Managers ChangeDates
000005 6 Alden Cantrell,Cierra Vega,Kierra Gentry,Miranda Shaffer,Pierre Cox,Thomas Crane 2017-11-29,2017-10-05,2018-09-05,2020-04-27,2018-11-06,2019-09-11
000360 1 Bradyn Kramer 2017-10-06
本次查询returns排序良好:
- 如果我删除
, count(distinct c.Manager) [ManagerChangesCount]
- 如果我删除字符串 id=10(第二个客户端)
- 如果我添加过滤条件
where ClCode = '000005'
- 如果我删除数据集中的重复行并从子查询中删除分组依据
但对我来说都一样,它看起来像一个错误......我的意思是我的查询结果未排序
伙计们,如果你能解决这个问题,请帮助我理解为什么排序不起作用
首先,我同意您所遇到的行为不应该发生,但是,Stack Overflow 不是用于报告应用程序错误的。对于 SQL 服务器,应该在他们的 Azure Feedback portal.
中完成
至于解决问题,从您的 COUNT
中删除多余的 DISTINCT
会使问题消失。要实现 DISTINCT
(在 SELECT DISTINCT
或 COUNT(DISTINCT {expression})
中)SQL 服务器需要首先对结果进行排序,然后它可以轻松删除任何具有相同排序的值位置。因此,即使它们具有明确的 ORDER BY
子句,也在您的 STRING_AGG
表达式中表达了排序。
我之所以说你的 DISTINCT
是多余的,是因为在查询的那个点上,对于 ClCode
的给定值,不会有 Manager
的重复值。这是因为您已经在子查询中对 Manager
和 ClCode
进行了分组。如果您 运行 单独查询,您会看到 Manager
没有任何重复项:
WITH tbl AS
(SELECT Id,
ClCode,
Manager,
ChangeDate
FROM (VALUES (1, '000005', 'Cierra Vega', '2017-10-05'),
(2, '000005', 'Alden Cantrell', '2017-11-29'),
(3, '000005', 'Alden Cantrell', '2017-11-30'),
(4, '000005', 'Kierra Gentry', '2018-09-05'),
(5, '000005', 'Kierra Gentry', '2018-09-12'),
(6, '000005', 'Pierre Cox', '2018-11-06'),
(7, '000005', 'Thomas Crane', '2019-09-11'),
(8, '000005', 'Thomas Crane', '2019-10-01'),
(9, '000005', 'Miranda Shaffer', '2020-04-27'),
(10, '000360', 'Bradyn Kramer', '2017-10-06')) t (Id, ClCode, Manager, ChangeDate) )
SELECT x.ClCode,
x.[Manager],
MIN(x.ChangeDate) AS [MinChangeDate]
FROM tbl x
GROUP BY x.ClCode,
x.[Manager];
因此,COUNT
中的 DISTINCT
只是为实例增加了开销,因为它不是必需的(SQL 服务器已经为 GROUP BY
那么为什么要让它重新排序呢?)。如果您 Are 在已经聚合的查询中使用 DISTINCT
,那么您很可能不需要它。
为了在动态生成的数据集上重现这个问题,我已经崩溃了,但它终于成功了!
这是代码
;with tbl as
(
select Id, ClCode, Manager, ChangeDate
from (values
(1, '000005', 'Cierra Vega', '2017-10-05'),
(2, '000005', 'Alden Cantrell', '2017-11-29'),
(3, '000005', 'Alden Cantrell', '2017-11-30'),
(4, '000005', 'Kierra Gentry', '2018-09-05'),
(5, '000005', 'Kierra Gentry', '2018-09-12'),
(6, '000005', 'Pierre Cox', '2018-11-06'),
(7, '000005', 'Thomas Crane', '2019-09-11'),
(8, '000005', 'Thomas Crane', '2019-10-01'),
(9, '000005', 'Miranda Shaffer', '2020-04-27'),
(10,'000360', 'Bradyn Kramer', '2017-10-06')
) as t(Id, ClCode, Manager, ChangeDate)
)
, grouped as
(
select c.ClCode
, count(distinct c.Manager) [ManagerChangesCount]
, STRING_AGG(c.[Manager], ',') within group (order by c.MinChangeDate) [Managers]
, STRING_AGG(c.MinChangeDate, ',') within group (order by c.MinChangeDate) [ChangeDates]
from (
select x.ClCode
, x.[Manager]
, min(x.ChangeDate) [MinChangeDate]
from tbl x
group by x.ClCode, x.[Manager]
) c
group by c.ClCode
)
select *
from grouped
我的示例数据集包含有关某些客户 (ClCode) 何时 (ChangeDate) 更改其经理 (Manager) 的数据。它是真正的 DWH 客户维度 table(SCD 类型 2)的一部分,因此这些 "duplicates" 只包含其他列某处的更改。
我想要实现的目标:我需要一个客户代码列表,其中包含他们的经理更换了多少次,以及这些经理姓名的逗号分隔列表,这些名称按更改顺序从左到右排序
ClCode ManagerChangesCount Managers ChangeDates
000005 6 Cierra Vega,Alden Cantrell,Kierra Gentry,Pierre Cox,Thomas Crane,Miranda Shaffer 2017-10-05,2017-11-29,2018-09-05,2018-11-06,2019-09-11,2020-04-27
000360 1 Bradyn Kramer 2017-10-06
但事实上我收到的结果没有或有一些奇怪的排序
ClCode ManagerChangesCount Managers ChangeDates
000005 6 Alden Cantrell,Cierra Vega,Kierra Gentry,Miranda Shaffer,Pierre Cox,Thomas Crane 2017-11-29,2017-10-05,2018-09-05,2020-04-27,2018-11-06,2019-09-11
000360 1 Bradyn Kramer 2017-10-06
本次查询returns排序良好:
- 如果我删除
, count(distinct c.Manager) [ManagerChangesCount]
- 如果我删除字符串 id=10(第二个客户端)
- 如果我添加过滤条件
where ClCode = '000005'
- 如果我删除数据集中的重复行并从子查询中删除分组依据
但对我来说都一样,它看起来像一个错误......我的意思是我的查询结果未排序
伙计们,如果你能解决这个问题,请帮助我理解为什么排序不起作用
首先,我同意您所遇到的行为不应该发生,但是,Stack Overflow 不是用于报告应用程序错误的。对于 SQL 服务器,应该在他们的 Azure Feedback portal.
中完成至于解决问题,从您的 COUNT
中删除多余的 DISTINCT
会使问题消失。要实现 DISTINCT
(在 SELECT DISTINCT
或 COUNT(DISTINCT {expression})
中)SQL 服务器需要首先对结果进行排序,然后它可以轻松删除任何具有相同排序的值位置。因此,即使它们具有明确的 ORDER BY
子句,也在您的 STRING_AGG
表达式中表达了排序。
我之所以说你的 DISTINCT
是多余的,是因为在查询的那个点上,对于 ClCode
的给定值,不会有 Manager
的重复值。这是因为您已经在子查询中对 Manager
和 ClCode
进行了分组。如果您 运行 单独查询,您会看到 Manager
没有任何重复项:
WITH tbl AS
(SELECT Id,
ClCode,
Manager,
ChangeDate
FROM (VALUES (1, '000005', 'Cierra Vega', '2017-10-05'),
(2, '000005', 'Alden Cantrell', '2017-11-29'),
(3, '000005', 'Alden Cantrell', '2017-11-30'),
(4, '000005', 'Kierra Gentry', '2018-09-05'),
(5, '000005', 'Kierra Gentry', '2018-09-12'),
(6, '000005', 'Pierre Cox', '2018-11-06'),
(7, '000005', 'Thomas Crane', '2019-09-11'),
(8, '000005', 'Thomas Crane', '2019-10-01'),
(9, '000005', 'Miranda Shaffer', '2020-04-27'),
(10, '000360', 'Bradyn Kramer', '2017-10-06')) t (Id, ClCode, Manager, ChangeDate) )
SELECT x.ClCode,
x.[Manager],
MIN(x.ChangeDate) AS [MinChangeDate]
FROM tbl x
GROUP BY x.ClCode,
x.[Manager];
因此,COUNT
中的 DISTINCT
只是为实例增加了开销,因为它不是必需的(SQL 服务器已经为 GROUP BY
那么为什么要让它重新排序呢?)。如果您 Are 在已经聚合的查询中使用 DISTINCT
,那么您很可能不需要它。