带串联的动态枢轴

问题描述 投票:0回答:1

应如何修改 SQL 以将文本“Name”连接到列标题和 2 个数据透视数据的名称字段中?

我有这样的桌子:

UmpID 第N 最后N 年龄
1 A H J
2 B S
3 C J A
4 D K J
5 E L S
6 F M J
7 G N J

查询:

SET NoCount ON;

DECLARE @cols AS NVARCHAR(MAX), @sql AS NVARCHAR(MAX);

WITH GS AS(
SELECT LastN, Age, QUOTENAME(Row_Number() OVER(PARTITION BY Age ORDER BY Age, LastN)) As GrpSeq FROM Umpires),
DS AS
(SELECT DISTINCT GrpSeq FROM GS),
CS AS
(SELECT STRING_AGG(GrpSeq,',') AS G FROM DS)

SELECT @cols = G FROM CS

SELECT @sql = 'SELECT *
            FROM (SELECT LastN, Age, Row_Number() OVER(PARTITION BY Age ORDER BY Age, LastN) As GrpSeq FROM Umpires) AS Q
            PIVOT(Min(LastN) FOR GrpSeq IN(' + @cols + ')) AS P;';

EXEC sp_executesql @sql;

产生输出:

年龄 1 2 3 4
A J
J H K M N
S L

我想制作:

年龄 姓名1 姓名2 姓名3 姓名4
A J、C
J H、A K、D M、F N、G
S 我,B L、E

尝试简单串联内部 SELECT 中的字段并引用 PIVOT 中的别名字段来构建 @sql 字符串生成的错误:

为变量赋值的 select 语句不得与数据检索操作结合使用

尝试连接“名称”字符串只会触发:

“名称”附近的语法不正确

作为旁注,这在 Access 查询中很容易完成,尽管由于 DCount() 域聚合函数,对于非常大的数据集可能会非常慢:

TRANSFORM Max([LastN] & ", " & [FirstN]) AS FullName
SELECT Umpires.Age
FROM Umpires
GROUP BY Umpires.Age
PIVOT "Name" & DCount("*","Umpires","Age='" & [Age] & "' AND UmpID<=" & [UmpID]);

我还可以在静态 SQLServer 数据透视表中生成已知数量的列标题值:

WITH DS AS(
SELECT Age, LastN + ', ' + FirstN AS FN, 'Name' + CAST(Row_Number() OVER(PARTITION BY Age ORDER BY Age, LastN) AS VARCHAR) As GrpSeq FROM Umpires)

SELECT * FROM (SELECT Age, FN, GrpSeq FROM DS) AS Q PIVOT(Max(FN) FOR GrpSeq IN([Name1],[Name2],[Name3],[Name4])) P;
sql sql-server pivot
1个回答
0
投票

可能会发生这样的事情:

DECLARE @cols AS NVARCHAR(MAX), @cols2 NVARCHAR(MAX), @sql AS NVARCHAR(MAX);

SELECT  *
INTO    #data
FROM    (
    VALUES  (1, N'A', N'H', N'J')
    ,   (2, N'B', N'I', N'S')
    ,   (3, N'C', N'J', N'A')
    ,   (4, N'D', N'K', N'J')
    ,   (5, N'E', N'L', N'S')
    ,   (6, N'F', N'M', N'J')
    ,   (7, N'G', N'N', N'J')
) t (UmpID,FirstN,LastN,Age)

;WITH GS AS(
    SELECT  LastN, Age
    ,   Row_Number() OVER(PARTITION BY Age ORDER BY Age, LastN) AS GrpSeq
    FROM    #data
    )
,DS AS (
    SELECT  DISTINCT GrpSeq
    FROM    GS
    )
,CS AS (
    SELECT  STRING_AGG(QUOTENAME(GrpSeq),',') WITHIN GROUP(ORDER BY GrpSeq) AS G
    ,   STRING_AGG(CONCAT(QUOTENAME(GrpSeq), ' AS Name', GrpSeq),',') WITHIN GROUP(ORDER BY GrpSeq) AS G2
    FROM    DS
    )
SELECT  @cols = G
,   @cols2 = G2
FROM    CS

SELECT  @sql = 'SELECT Age, ' + @cols2 + N'
            FROM (SELECT CONCAT(LastN, '','', FirstN) AS LastN, Age, Row_Number() OVER(PARTITION BY Age ORDER BY Age, LastN) As GrpSeq FROM #data) AS Q
            PIVOT(Min(LastN) FOR GrpSeq IN(' + @cols + ')) AS P;';

EXEC    sp_executesql @sql;

我创建了第二个名为

@cols2
的变量,它执行
[1] AS Name1, ... [N] AS NameN
选择字符串,连接
CONCAT(LastN, '','', FirstN)
以创建名字 + 姓氏组合,然后执行您已经执行的操作。

我还在 STRING_AGG 中添加了“WITHIN GROUP”,以确保列的顺序正确。

条件聚合版本(上面合并的一些代码):

;WITH GS AS(
    SELECT  LastN, Age
    ,   Row_Number() OVER(PARTITION BY Age ORDER BY Age, LastN) AS GrpSeq
    FROM    #data
    )
,DS AS (
    SELECT  DISTINCT GrpSeq
    FROM    GS
    )
,CS AS (
    SELECT  STRING_AGG(CONCAT('MAX(CASE WHEN GrpSeq = ', GrpSeq, ' THEN LastN END)', ' AS Name', GrpSeq),',') WITHIN GROUP(ORDER BY GrpSeq) AS G3
    FROM    DS
    )
SELECT  @cols = G3
FROM    CS

SELECT  @sql = '
   SELECT Age, ' + @cols + N'
   FROM (SELECT CONCAT(LastN, '','', FirstN) AS LastN, Age, Row_Number() OVER(PARTITION BY Age ORDER BY Age, LastN) As GrpSeq FROM #data) AS Q
   GROUP BY Age
'
© www.soinside.com 2019 - 2024. All rights reserved.