将列值聚合到列表中会产生错误

Aggregate column values into a list produces an error

以下查询

DECLARE @SNH TABLE 
(
    dt date, 
    QueueName varchar(10),
    SN varchar(10)
)

INSERT INTO @SNH (Dt, QueueName, SN)
VALUES ('2001-04-04', 'Queue01', 'Q01SN01'),
       ('2001-04-05', 'Queue01', 'Q01SN01'),
       ('2001-04-06', 'Queue01', 'Q01SN01'),
       ('2001-04-04', 'Queue02', 'Q02SN01'),
       ('2001-04-05', 'Queue02', 'Q02SN01'),
       ('2001-04-06', 'Queue02', 'Q02SN02')

DECLARE @QH TABLE 
(
    DT date, 
    QueueName varchar(10)
)  

INSERT INTO @QH(DT, QueueName)
VALUES ('2001-04-04','Queue01'),
       ('2001-04-05','Queue01'),
       ('2001-04-06','Queue01'),
       ('2001-04-04','Queue02'),
       ('2001-04-05','Queue02'),
       ('2001-04-06','Queue02')

SELECT DISTINCT 
    q.QueueName clnQueueName,
    MIN(q.Dt) OVER (PARTITION BY q.QueueName) clnStartDate,
    MAX(q.Dt) OVER (PARTITION BY q.QueueName) clnEndDate,
    s.SN
FROM 
    @QH q
LEFT JOIN 
    @SNH s ON s.QueueName = q.QueueName 

returns 这个输出:

clnQueueName clnStartDate clnEndDate SN
Queue01 2001-04-04 2001-04-06 Q01SN01
Queue02 2001-04-04 2001-04-06 Q02SN01
Queue02 2001-04-04 2001-04-06 Q02SN02

我的目标是用

聚合成逗号分隔的列表
SELECT DISTINCT 
    q.QueueName clnQueueName,
    MIN(q.Dt) OVER (PARTITION BY q.QueueName) clnStartDate,
    MAX(q.Dt) OVER (PARTITION BY q.QueueName) clnEndDate,
    STRING_AGG(s.SN,',')
FROM 
    @QH q
LEFT JOIN 
    @SNH s ON s.QueueName = q.QueueName AND s.Dt = q.Dt

如下

clnQueueName clnStartDate clnEndDate SN
Queue01 2001-04-04 2001-04-06 Q01SN01
Queue02 2001-04-04 2001-04-06 Q02SN01,Q02SN02

相反,我得到:

Msg 8120, Level 16, State 1, Line 36
Column '@QH.QueueName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

抱歉,我听不懂。

@QH.QueueName甚至没有在SELECT中提到,只有q.QueueName.

我在这里缺少什么?

根据 the docs,如果 string_agg 不是唯一选择的项目,则需要 group by 子句。正确分组后,您不再需要 window 函数或 distinct.

要仅获取 SN 的不同值,您需要分组两次,第一次在 sub-query 中(在本例中为 CTE)以获得 SN 的不同值,并且第二次使用 string_agg 以获得 QueueName.

的不同值
WITH cte AS (
    SELECT
        q.QueueName clnQueueName
        , MIN(q.Dt) clnStartDate
        , MAX(q.Dt) clnEndDate
        , s.SN
    FROM @QH q
    LEFT JOIN @SNH s
        ON s.QueueName = q.QueueName AND s.Dt = q.Dt
    GROUP BY q.QueueName, s.SN
)
SELECT clnQueueName
    , MIN(clnStartDate) clnStartDate
    , MAX(clnEndDate) clnEndDate
    , STRING_AGG(SN,',') SN
FROM cte
GROUP BY clnQueueName;

Returns:

clnQueueName clnStartDate clnEndDate SN
Queue01 2001-04-04 2001-04-06 Q01SN01
Queue02 2001-04-04 2001-04-06 Q02SN01,Q02SN02