The following query
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 this output:
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 |
which I'm aiming to aggregate into a comma separated list with
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
as follows
clnQueueName | clnStartDate | clnEndDate | SN |
Queue01 | 2001-04-04 | 2001-04-06 | Q01SN01 |
Queue02 | 2001-04-04 | 2001-04-06 | Q02SN01,Q02SN02 |
Instead I get:
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
Sorry, I can't get it.
@QH.QueueName
isn't even mentioned in the SELECT
, only q.QueueName
.
What I am missing here?
CodePudding user response:
As per the docs, a group by
clause is required if the string_agg
is not the only item being selected. Once grouping correctly you no longer need window functions or distinct
.
To obtain only distinct values of SN
you need to group twice, the first time in a sub-query (in this case a CTE) to get distinct values of SN
and the second time with string_agg
to get distinct values of 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 |