当数据具有 NULL 值时,如何使用 SQL 服务器中的 Pivot 将多行转换为多列的一行
How to convert multiple rows into one row with multiple columns using Pivot in SQL Server when data having NULL values
我有一个 table,我想在某些条件下从中获取数据。我正在通过以下查询获取数据。
SELECT track,
ytd,
weekno,
[unit]
FROM SMIrawdataFinal
WHERE unit IS NOT NULL AND tracktype='focus' AND track='A' AND ytd IS NOT NULL
原table(数据)如下
track ytd weekno unit
A (Blank) 1 1
A (Blank) 2 2
A (Blank) 3 3
A 19 5 5
A (Blank) 4 4
我在 sql 服务器中使用 PIVOT 获得了以下数据。我的问题是
如何删除空值并在一行中获取相同的数据。
autoId track ytd col4 col3 col2 col1
-------------------------------------------------
1 A (Blank) NULL 4 3 2
2 A 19 5 NULL NULL NULL
下面是我的SQL查询:
SELECT *
FROM (
SELECT track,ytd,weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
AND ytd IS NOT NULL
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS pivot1
如果您使用 SQL 服务器并且您喜欢将 col4
到 col1
连接到一行,您可以这样实现:
SELECT p.track, p.ytd,
CONVERT(nvarchar(max),ISNULL(p.[5],0))
+ CONVERT(nvarchar(max),ISNULL(p.[4],0))
+ CONVERT(nvarchar(max),ISNULL(p.[3],0))
+ CONVERT(nvarchar(max),ISNULL(p.[2],0)) as asOneRow
FROM (
SELECT track, ytd, weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
AND ytd IS NOT NULL
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS p
如果你想把这些值加起来,你可以使用这个:
SELECT p.track, p.ytd,
SUM(ISNULL(p.[5],0)) as col4,
SUM(ISNULL(p.[4],0)) as col3,
SUM(ISNULL(p.[3],0)) as col2,
SUM(ISNULL(p.[2],0)) as col1
FROM (
SELECT track, ytd, weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
AND ytd IS NOT NULL
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS p
GROUP BY p.track, p.ytd
根据您的示例数据和查询,我已将其设为单行,请在您的查询中添加 where 条件
declare @t table (track varchar(2),ytd int,weekno int,unit iNT)
insert into @t (track,ytd,weekno,unit)
values
('A',NULL,1,1),
('A',NULL,2,2),
('A',NULL,3,3),
('A',19,5,5),
('A',NULL,4,4)
;with CTE AS (
SELECT * FROM (SELECT track,ytd,weekno,[unit]
FROM @t ) as s PIVOT
(SUM(unit) FOR weekno in ([5],[4],[3],[2]))AS pivot1)
Select track,MAX(ytd)As YTD,MAX([5])AS [5],MAX([4])AS [4],MAX([3])AS [3],MAX([2])AS [2] from CTE
GROUP BY track
动态版本
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
GO
CREATE table #t
(track varchar(2),ytd int,weekno VARCHAR(5),unit INT)
insert into #t (track,ytd,weekno,unit)values
('A',NULL,1,1),
('A',NULL,2,2),
('A',NULL,3,3),
('A',19,5,5),
('A',NULL,4,4)
DECLARE @statement NVARCHAR(max)
,@columns NVARCHAR(max)
SELECT @columns = ISNULL(@columns + ',', '') + N'[' + tbl.weekno + ']'
FROM (
SELECT DISTINCT weekno
FROM #t
) AS tbl
SELECT @statement = ' select track,
MAX(ytd)As YTD,
MAX([5])AS [5],
MAX([4])AS [4],
MAX([3])AS [3],
MAX([2])AS [2] from (
SELECT * FROM (SELECT track,ytd,weekno,[unit]
FROM #t ) as s PIVOT
(SUM(unit) FOR weekno in(' + @columns + ')) as pvt)T
GROUP BY T.track'
EXEC sp_executesql @statement = @statement
将分组依据与 SUM 结合使用以获得所需的输出:
SELECT track,
SUM(ISNULL(ytd, 0)) AS [ytd],
SUM(ISNULL([5], 0)) AS [5],
SUM(ISNULL([4], 0)) AS [4],
SUM(ISNULL([3], 0)) AS [3],
SUM(ISNULL([2], 0)) AS [2]
FROM (SELECT track,ytd,weekno,[unit]
FROM SMIrawdataFinal where album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A') as s PIVOT
(SUM(unit) FOR weekno in ([5],[4],[3],[2]))AS pivot1
GROUP BY track
输出:
track | ytd | 5 | 4 | 3 | 2
--------------------------------
A | 19 | 5 | 4 | 3 | 2
我建议您在 select 上使用聚合并按轨道分组。
CREATE TABLE #t
(
track VARCHAR(10),
ytd INT,
weekno INT,
unit INT
)
INSERT INTO #t VALUES
('A', NULL, 1, 1),
('A', NULL, 2, 2),
('A', NULL, 3, 3),
('A', 19, 5, 5),
('A', NULL, 4, 4)
SELECT track,
MAX(COALESCE(ytd, 0)) [ytd],
MAX(COALESCE([5], 0)) [5],
MAX(COALESCE([4], 0)) [4],
MAX(COALESCE([3], 0)) [3],
MAX(COALESCE([2], 0)) [2]
FROM (
SELECT track,
ytd,
weekno,
[unit]
FROM #t
WHERE unit IS NOT NULL AND track = 'A'
) as x
PIVOT
(
SUM(unit)
FOR weekno IN ([5],[4],[3],[2])
)AS piv
GROUP BY track
DROP TABLE #t
输出:
track ytd 5 4 3 2
A 19 5 4 3 2
我觉得还是好好想想这样做是否合理"merge"。为什么 weekno 5 到 2 的 YTD 都与 19 相同?如果 YTD 是 Year To Date,则不同的周数不应该相同。所以我的建议是放弃 YTD。
SELECT *
FROM (
SELECT track,/*ytd,*/ weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
/*AND ytd IS NOT NULL*/
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS pivot1
我有一个 table,我想在某些条件下从中获取数据。我正在通过以下查询获取数据。
SELECT track,
ytd,
weekno,
[unit]
FROM SMIrawdataFinal
WHERE unit IS NOT NULL AND tracktype='focus' AND track='A' AND ytd IS NOT NULL
原table(数据)如下
track ytd weekno unit
A (Blank) 1 1
A (Blank) 2 2
A (Blank) 3 3
A 19 5 5
A (Blank) 4 4
我在 sql 服务器中使用 PIVOT 获得了以下数据。我的问题是 如何删除空值并在一行中获取相同的数据。
autoId track ytd col4 col3 col2 col1
-------------------------------------------------
1 A (Blank) NULL 4 3 2
2 A 19 5 NULL NULL NULL
下面是我的SQL查询:
SELECT *
FROM (
SELECT track,ytd,weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
AND ytd IS NOT NULL
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS pivot1
如果您使用 SQL 服务器并且您喜欢将 col4
到 col1
连接到一行,您可以这样实现:
SELECT p.track, p.ytd,
CONVERT(nvarchar(max),ISNULL(p.[5],0))
+ CONVERT(nvarchar(max),ISNULL(p.[4],0))
+ CONVERT(nvarchar(max),ISNULL(p.[3],0))
+ CONVERT(nvarchar(max),ISNULL(p.[2],0)) as asOneRow
FROM (
SELECT track, ytd, weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
AND ytd IS NOT NULL
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS p
如果你想把这些值加起来,你可以使用这个:
SELECT p.track, p.ytd,
SUM(ISNULL(p.[5],0)) as col4,
SUM(ISNULL(p.[4],0)) as col3,
SUM(ISNULL(p.[3],0)) as col2,
SUM(ISNULL(p.[2],0)) as col1
FROM (
SELECT track, ytd, weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
AND ytd IS NOT NULL
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS p
GROUP BY p.track, p.ytd
根据您的示例数据和查询,我已将其设为单行,请在您的查询中添加 where 条件
declare @t table (track varchar(2),ytd int,weekno int,unit iNT)
insert into @t (track,ytd,weekno,unit)
values
('A',NULL,1,1),
('A',NULL,2,2),
('A',NULL,3,3),
('A',19,5,5),
('A',NULL,4,4)
;with CTE AS (
SELECT * FROM (SELECT track,ytd,weekno,[unit]
FROM @t ) as s PIVOT
(SUM(unit) FOR weekno in ([5],[4],[3],[2]))AS pivot1)
Select track,MAX(ytd)As YTD,MAX([5])AS [5],MAX([4])AS [4],MAX([3])AS [3],MAX([2])AS [2] from CTE
GROUP BY track
动态版本
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
GO
CREATE table #t
(track varchar(2),ytd int,weekno VARCHAR(5),unit INT)
insert into #t (track,ytd,weekno,unit)values
('A',NULL,1,1),
('A',NULL,2,2),
('A',NULL,3,3),
('A',19,5,5),
('A',NULL,4,4)
DECLARE @statement NVARCHAR(max)
,@columns NVARCHAR(max)
SELECT @columns = ISNULL(@columns + ',', '') + N'[' + tbl.weekno + ']'
FROM (
SELECT DISTINCT weekno
FROM #t
) AS tbl
SELECT @statement = ' select track,
MAX(ytd)As YTD,
MAX([5])AS [5],
MAX([4])AS [4],
MAX([3])AS [3],
MAX([2])AS [2] from (
SELECT * FROM (SELECT track,ytd,weekno,[unit]
FROM #t ) as s PIVOT
(SUM(unit) FOR weekno in(' + @columns + ')) as pvt)T
GROUP BY T.track'
EXEC sp_executesql @statement = @statement
将分组依据与 SUM 结合使用以获得所需的输出:
SELECT track,
SUM(ISNULL(ytd, 0)) AS [ytd],
SUM(ISNULL([5], 0)) AS [5],
SUM(ISNULL([4], 0)) AS [4],
SUM(ISNULL([3], 0)) AS [3],
SUM(ISNULL([2], 0)) AS [2]
FROM (SELECT track,ytd,weekno,[unit]
FROM SMIrawdataFinal where album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A') as s PIVOT
(SUM(unit) FOR weekno in ([5],[4],[3],[2]))AS pivot1
GROUP BY track
输出:
track | ytd | 5 | 4 | 3 | 2
--------------------------------
A | 19 | 5 | 4 | 3 | 2
我建议您在 select 上使用聚合并按轨道分组。
CREATE TABLE #t
(
track VARCHAR(10),
ytd INT,
weekno INT,
unit INT
)
INSERT INTO #t VALUES
('A', NULL, 1, 1),
('A', NULL, 2, 2),
('A', NULL, 3, 3),
('A', 19, 5, 5),
('A', NULL, 4, 4)
SELECT track,
MAX(COALESCE(ytd, 0)) [ytd],
MAX(COALESCE([5], 0)) [5],
MAX(COALESCE([4], 0)) [4],
MAX(COALESCE([3], 0)) [3],
MAX(COALESCE([2], 0)) [2]
FROM (
SELECT track,
ytd,
weekno,
[unit]
FROM #t
WHERE unit IS NOT NULL AND track = 'A'
) as x
PIVOT
(
SUM(unit)
FOR weekno IN ([5],[4],[3],[2])
)AS piv
GROUP BY track
DROP TABLE #t
输出:
track ytd 5 4 3 2
A 19 5 4 3 2
我觉得还是好好想想这样做是否合理"merge"。为什么 weekno 5 到 2 的 YTD 都与 19 相同?如果 YTD 是 Year To Date,则不同的周数不应该相同。所以我的建议是放弃 YTD。
SELECT *
FROM (
SELECT track,/*ytd,*/ weekno,[unit]
FROM SMIrawdataFinal
WHERE album = 'XYZ'
AND unit IS NOT NULL
AND tracktype='focus'
AND track='A'
/*AND ytd IS NOT NULL*/
) as s
PIVOT(
SUM(unit)
FOR weekno in ([5],[4],[3],[2])
)AS pivot1