在sql中使用pivot的多行
Posted
技术标签:
【中文标题】在sql中使用pivot的多行【英文标题】:Multiple rows using pivot in sql 【发布时间】:2020-10-05 09:10:03 【问题描述】:我有一张桌子。
Item | ID
--------------
1-A | 213
2-B | 432
3-C | 267
3-C | 879
3-C | 467
我使用枢轴。
Select * from (
Select ID,Item
From data1
)R
Pivot (
Max(ID) For Item
in
([1-A],[2-B],[3-C])
)as pvt
但我只能得到一个值。
1-A | 2-B | 3-C
-----------------
213 | 453 | 467
怎样才能得到3-C的所有值,希望能得到这个结果。
1-A | 2-B | 3-C | 3-C | 3-C
---------------------------
213 | 453 | 267 | 879 | 467
但是3-C,可能有一个或多个,我无法控制会出现多少个。
希望能帮忙解答,谢谢。
【问题讨论】:
可以有多少行,总是5行吗?当所述行的Item
具有相同的值(因为它显然不是 ID
)时,是什么决定了所述行的顺序,还是顺序无关紧要?
目前只有3-C会有多个,至少有一个,最多有多个,也就是3-C会有多个情况
“最多”? Many 不是数字。这是否意味着行数不确定?我在评论中问的其余部分呢?
是的,行数不定,顺序无所谓。如果可以的话,希望能按照我的结果显示
【参考方案1】:
这里真正的问题是行数无法确定。这意味着您需要动态 SQL,下一个问题是您没有唯一的值可以作为枢轴,因此我们还需要对ROW_NUMBER
进行创新。这给出了这个,它不是特别漂亮,但“有效”。
CREATE TABLE dbo.YourTable (Item char(3),
ID int);
INSERT INTO dbo.YourTable (Item,
ID)
VALUES('1-A',213),
('2-B',432),
('3-C',267),
('3-C',879),
('3-C',467);
GO
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
DECLARE @Delimiter nvarchar(30) = N',' + @CRLF + N' ';
WITH RNs AS(
SELECT Item,
ID,
ROW_NUMBER() OVER (ORDER BY Item) AS RN
FROM dbo.YourTable)
SELECT @SQL = N'WITH RNs AS(' + @CRLF +
N' SELECT Item,' + @CRLF +
N' ID,' + @CRLF +
N' ROW_NUMBER() OVER (ORDER BY Item) AS RN' + @CRLF +
N' FROM dbo.YourTable)' + @CRLF +
N'SELECT ' +
STRING_AGG(CONCAT(N'MAX(CASE WHEN Item = ',QUOTENAME(R.Item,''''),N' AND RN = ',R.RN,N' THEN R.ID END) AS ',QUOTENAME(R.Item)),@Delimiter) WITHIN GROUP (ORDER BY R.Item, R.RN) + @CRLF +
N'FROM RNs R;'
FROM RNs R;
PRINT @SQL;
EXEC sys.sp_executesql @SQL;
GO
DROP TABLE dbo.YourTable;
我假设您使用的是最新版本的 SQL Server。如果不是,您需要将 STRING_AGG
替换为旧的 FOR XML PATH
方法。
DB<>Fiddle
【讨论】:
【参考方案2】:您需要使用Dynamic SQL
,因为您的列数未知。查询是动态形成的,使用sp_executesql
执行查询
看起来您想要 Item
和 ID
组合的独特值,所以我在这里使用 GROUP BY Item, ID
。
declare @sql nvarchar(max)
SELECT @sql = isnull(@sql + ',', 'SELECT ')
+ CONVERT(VARCHAR(10), ID) + ' AS ' + QUOTENAME(Item)
FROM data1
GROUP BY Item, ID
ORDER BY Item, ID
-- PRINT @sql
exec sp_executesql @sql
例如:dbfiddle
【讨论】:
你好像输了一排;你有 5 列,但在小提琴中有 6 行。 2 行是相同的。我怀疑 OP 想要重复的项目和 ID 值。特意添加它来说明这一点。【参考方案3】:另一种方法是将结果放在3-C
值的单个列中,使用string_agg()
:
select string_agg(case when item = '[1-A]' then id end, ',') within group (order by id) as id_1_a,
string_agg(case when item = '[2-B]' then id end, ',') within group (order by id) as id_2_b,
string_agg(case when item = '[3-C]' then id end, ',') within group (order by id) as id_3_c
from data1;
这不是您指定的确切结果集,但它可能会满足您的需求。
【讨论】:
以上是关于在sql中使用pivot的多行的主要内容,如果未能解决你的问题,请参考以下文章