如何在数据透视表上将多行合并为一行 table
How to collapse multiple rows into one on a pivot table
我在 SQL 代码方面相对缺乏经验,所以这里开始。
我想从 table 中提取数据并使用 PIVOT 将值转换为列标题。
我已经设法使用 PIVOT 命令(和动态字段名称)实现了我想要的,但我希望针对单个引用的所有值都出现在一行中。但是,我为每个代码得到一行,原始 table 中有一个值(请参见下面的结果)。
使用 CROSS APPLY 似乎是可行的方法(它在我的代码示例中被注释掉了)但是我遇到了一些问题:
- 我无法理解它是如何工作的,因此根据我的情况调整在线示例涉及一些猜测工作。
- 我根据此站点上的另一个 post 在命令中输入了(我认为是)正确的引用:
Pivot a table on a value but group the data on one line by another?
他们声称 VALUES 中的两个值需要是相同的数据类型才能使反透视过程起作用。但是,将 'value' 设置为 varchar(10) 会阻止 SUM 函数在 PIVOT 语句中工作。 运行 它作为 decimal/float 产生所有 NULL 结果。
- 使用 'value' set decimal 包括 GROUP BY 语句确实会产生一行数据,但是(如第 2 点)所有代码值为 NULL。
希望这一切都有意义。请建议我如何将下面的结果折叠成一行。提前致谢。
DECLARE @CODES nvarchar(max)
select @CODES =
stuff(
(
select distinct ',[' + code + ']'
from codetable
for xml path('')
),
1,1,'')
DECLARE @SQL nvarchar(max)
SET @SQL =
N'
SELECT
ref,
' + @CODES + ',
FROM
codetable
--CROSS APPLY
--(
-- VALUES
-- (''code'', convert(varchar(10), code, 120)),
-- (''value'', convert(decimal, value))
--) CA (CODE, VAL)
PIVOT(SUM(value)
FOR code IN (' + @CODES + '))
AS PVTTable2
WHERE
ref = ''101'' AND end_date IS NULL
GROUP BY ref,' + @CODES + '
'
exec sp_executesql @SQL
My original table is like this:
-------------------------
|ref |CODES |VALUE |
-------------------------
|101 |CODE4 |20 |
|101 |CODE1 |2 |
|101 |CODE7 |38 |
The results I get are:
-------------------------------------------------------------------------
|ref |CODE1 |CODE2 |CODE3 |CODE4 |CODE5 |CODE6 |CODE7 |CODE8 |
-------------------------------------------------------------------------
|101 |NULL |NULL |NULL |20 |NULL |NULL |NULL |NULL |
|101 |2 |NULL |NULL |NULL |NULL |NULL |NULL |NULL |
|101 |NULL |NULL |NULL |NULL |NULL |NULL |38 |NULL |
GROUP BY ref
仅
DECLARE @CODES nvarchar(max)
select @CODES =
stuff(
(
select distinct ',[' + code + ']'
from codetable
for xml path('')
),
1,1,'');
DECLARE @CODESGrp nvarchar(max)
select @CODESGrp =
stuff(
(
select distinct ',min([' + code + '])'
from codetable
for xml path('')
),
1,1,'');
DECLARE @SQL nvarchar(max);
SET @SQL = 'SELECT ref,' + @CODESGrp
+ ' FROM codetable '
+ ' PIVOT(SUM(value) FOR code IN (' + @CODES + ')) AS PVTTable2'
+ ' WHERE ref = 101 GROUP BY ref' ;
exec sp_executesql @SQL;
枢轴应该写成:
DECLARE @cols AS NVARCHAR(MAX),@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(T.CODES)
FROM codetable T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ref, ' + @cols + ' from
(
SELECT
ref, --< grouping column >,
CODES, --< spreading column >,
VALUE --< aggregation column >
FROM codetable
) PivotData
pivot
(
sum(VALUE)
for CODES in (' + @cols + ')
) p '
exec sp_executesql @query
我在 SQL 代码方面相对缺乏经验,所以这里开始。
我想从 table 中提取数据并使用 PIVOT 将值转换为列标题。
我已经设法使用 PIVOT 命令(和动态字段名称)实现了我想要的,但我希望针对单个引用的所有值都出现在一行中。但是,我为每个代码得到一行,原始 table 中有一个值(请参见下面的结果)。
使用 CROSS APPLY 似乎是可行的方法(它在我的代码示例中被注释掉了)但是我遇到了一些问题:
- 我无法理解它是如何工作的,因此根据我的情况调整在线示例涉及一些猜测工作。
- 我根据此站点上的另一个 post 在命令中输入了(我认为是)正确的引用: Pivot a table on a value but group the data on one line by another? 他们声称 VALUES 中的两个值需要是相同的数据类型才能使反透视过程起作用。但是,将 'value' 设置为 varchar(10) 会阻止 SUM 函数在 PIVOT 语句中工作。 运行 它作为 decimal/float 产生所有 NULL 结果。
- 使用 'value' set decimal 包括 GROUP BY 语句确实会产生一行数据,但是(如第 2 点)所有代码值为 NULL。
希望这一切都有意义。请建议我如何将下面的结果折叠成一行。提前致谢。
DECLARE @CODES nvarchar(max)
select @CODES =
stuff(
(
select distinct ',[' + code + ']'
from codetable
for xml path('')
),
1,1,'')
DECLARE @SQL nvarchar(max)
SET @SQL =
N'
SELECT
ref,
' + @CODES + ',
FROM
codetable
--CROSS APPLY
--(
-- VALUES
-- (''code'', convert(varchar(10), code, 120)),
-- (''value'', convert(decimal, value))
--) CA (CODE, VAL)
PIVOT(SUM(value)
FOR code IN (' + @CODES + '))
AS PVTTable2
WHERE
ref = ''101'' AND end_date IS NULL
GROUP BY ref,' + @CODES + '
'
exec sp_executesql @SQL
My original table is like this:
-------------------------
|ref |CODES |VALUE |
-------------------------
|101 |CODE4 |20 |
|101 |CODE1 |2 |
|101 |CODE7 |38 |
The results I get are:
-------------------------------------------------------------------------
|ref |CODE1 |CODE2 |CODE3 |CODE4 |CODE5 |CODE6 |CODE7 |CODE8 |
-------------------------------------------------------------------------
|101 |NULL |NULL |NULL |20 |NULL |NULL |NULL |NULL |
|101 |2 |NULL |NULL |NULL |NULL |NULL |NULL |NULL |
|101 |NULL |NULL |NULL |NULL |NULL |NULL |38 |NULL |
GROUP BY ref
仅
DECLARE @CODES nvarchar(max)
select @CODES =
stuff(
(
select distinct ',[' + code + ']'
from codetable
for xml path('')
),
1,1,'');
DECLARE @CODESGrp nvarchar(max)
select @CODESGrp =
stuff(
(
select distinct ',min([' + code + '])'
from codetable
for xml path('')
),
1,1,'');
DECLARE @SQL nvarchar(max);
SET @SQL = 'SELECT ref,' + @CODESGrp
+ ' FROM codetable '
+ ' PIVOT(SUM(value) FOR code IN (' + @CODES + ')) AS PVTTable2'
+ ' WHERE ref = 101 GROUP BY ref' ;
exec sp_executesql @SQL;
枢轴应该写成:
DECLARE @cols AS NVARCHAR(MAX),@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(T.CODES)
FROM codetable T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ref, ' + @cols + ' from
(
SELECT
ref, --< grouping column >,
CODES, --< spreading column >,
VALUE --< aggregation column >
FROM codetable
) PivotData
pivot
(
sum(VALUE)
for CODES in (' + @cols + ')
) p '
exec sp_executesql @query