SQL Pivot Table 没有将结果放在一行中
SQL Pivot Table Not Putting Results In One Line
我正在尝试在 SQL 中创建一个枢轴 table。我的结果并没有像我希望的那样被合并到每个 TID 的一行中。这个例子应该清楚我的问题:
Results:
TID NS_AM AS_AM NS_DB AS_DB
TID 1a 971 947
TID 2 807 974
TID 1a 954 910
TID 2 931 904
Desired Results:
TID NS_AM AS_AM NS_DB AS_DB
TID 1a 971 947 954 910
TID 2 807 974 931 904
编辑:这是从大型动态查询派生的。我无法输入该查询,因为它会使问题变得非常混乱。我必须使用 pivot/unpivot。
如有任何帮助,我们将不胜感激。下面是示例数据和生成我的结果的查询。
如您所见,AM 项目被合并到一行,DB 项目被合并到一行,但它们并没有像我希望的那样报告所有结果。
drop table if exists mock_data;
create table MOCK_DATA (
tid VARCHAR(50),
plantype VARCHAR(50),
ns VARCHAR(50),
[as] VARCHAR(50)
);
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '112', '048');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '142', '889');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '887', '668');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '093', '910');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '954', '266');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '822', '201');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '234', '083');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '527', '716');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '662', '168');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '795', '947');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '971', '588');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '755', '234');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '199', '603');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '164', '362');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '943', '462');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '971', '164');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '594', '822');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '467', '478');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '064', '591');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '639', '298');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '186', '797');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '226', '369');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '036', '272');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '807', '197');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '167', '402');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '477', '047');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '262', '974');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '268', '282');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '508', '069');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '303', '528');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '747', '325');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '293', '614');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '886', '221');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '652', '365');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '931', '904');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '089', '662');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '922', '497');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '722', '328');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '386', '324');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '402', '552');
SELECT [TID],
IsNull([NS_AM], '') AS [NS_AM],
IsNull([AS_AM], '') AS [AS_AM]
FROM
(
SELECT [TID],
[PlanType],
col+'_'+CAST(PlanType AS VARCHAR(50)) col,
value
FROM
(
SELECT PlanType,
[TID],
CAST(NS AS VARCHAR(100)) AS NS,
CAST(AS AS VARCHAR(100)) AS AS
FROM #temp
) s UNPIVOT(value FOR col IN(NS,
AS )) unpiv
) src PIVOT(MAX(value) FOR col IN([NS_AM],
[AS_AM],
[NS_DB],
[AS_DB]
)) p;
在此先感谢您。
Null 被用作替代品(作为一些缺失值的一些大随机数)这就是为什么它也如此独特。但是这里作为聚合函数确实会忽略空值,除了按照标准计数,尽管您也可以同时使用 min 和 max
进行检查
如果根据我的假设只有空值与上述不同
,您可以使用 group by
并取 min/max
Select TID, min(NS_AM), min( AS_AM),
min(NS_DB), min(AS_DB) Group by
TID.
使用 CROSS TABS 而不是取消和旋转数据,这可能会非常简单。
SELECT TID,
MAX( CASE WHEN PlanType = 'AM' THEN [ns] END) AS NS_AM,
MAX( CASE WHEN PlanType = 'AM' THEN [as] END) AS AS_AM,
MAX( CASE WHEN PlanType = 'DB' THEN [ns] END) AS NS_DB,
MAX( CASE WHEN PlanType = 'DB' THEN [as] END) AS AS_DB
FROM MOCK_DATA
GROUP BY TID;
如果你想使用动态代码,转换起来并不难。这只是您需要处理的每一列的复制粘贴编辑问题,代码将根据需要为 plantype 添加尽可能多的值。
DECLARE @SQL nvarchar(MAX)
SELECT @SQL = N'SELECT TID' + CHAR(10)
+ ( SELECT DISTINCT REPLACE( REPLACE(
CHAR(9) + ',MAX( CASE WHEN PlanType = <<quotedplantype>> THEN [ns] END) AS NS_<<plantype>>' + CHAR(10)
+ CHAR(9) + ',MAX( CASE WHEN PlanType = <<quotedplantype>> THEN [as] END) AS AS_<<plantype>>' + CHAR(10)
, '<<quotedplantype>>', QUOTENAME(plantype, '''')), '<<plantype>>', plantype)
FROM MOCK_DATA
FOR XML PATH(''), TYPE).value('./text()[1]', 'varchar(max)') +
+ N'FROM MOCK_DATA' + NCHAR(10)
+ N'GROUP BY TID;'
EXEC sp_executesql @SQL /*, @params_def, @param1, @param2,..., @paramN*/;
尝试将 "Order by TID" 添加到您的 PIVOT/UNPIVOT 表达式中。
您可以通过如下方式进行内部联接来获取所需的数据,无需数据透视!
select v1.tid,v1.m_ns[Ns_Am],v1.m_as[As_Am],v2.m_ns[NS_DB],V2.m_As[AS_DB] from(
select tid,plantype,max(ns)[m_ns],max([as]) [m_as] from MOCK_DATA group by tid,plantype) v1
inner join
(select tid,plantype,max(ns)[m_ns],max([as]) [m_as] from MOCK_DATA group by tid,plantype)v2
on v1.tid=v2.tid and v1.plantype='Am' and v2.plantype='DB'
你也可以使用这个你可以动态化的脚本(给我一些时间,我会为你做!)
select v1.tid,v1.[am] [ns_am],v1.[db][ns_db],v2.[am] [as_am],v2.[db][as_db] from
(select * from(
select tid,ns,[PlanType] from MOCK_DATA) s
pivot
(max(ns) for [PlanType] in ([AM],[DB]) )s
) v1
inner join
(
select * from(
select tid,[as],[PlanType] from MOCK_DATA) s
pivot
(max([as]) for [PlanType] in ([AM],[DB]) )s) v2
on v1.tid=v2.tid
这是承诺的动态解决方案,使用游标,而不是连接
它动态地将列添加到最终 table 并更新游标循环内的数据
IF EXISTS(SELECT 1 FROM sysobjects where name='myMOCK_DATA') drop table myMOCK_DATA
create table myMOCK_DATA (tid varchar(10));insert into myMOCK_DATA(tid) select distinct(tid) from MOCK_DATA
declare mycursor cursor for
select tid,plantype,max(ns)[m_ns],max([as])[m_as] from MOCK_DATA group by tid,plantype
declare @plantype as varchar(2);declare @tid as varchar(10);declare @m_ns as int;declare @m_as as int
declare @script as varchar(max);open mycursor
fetch mycursor into @tid,@plantype,@m_ns,@m_as
while @@fetch_status=0
begin
set @script='IF not EXISTS(SELECT 1 FROM sys.columns WHERE Name = ''NS_'+@plantype +''' AND Object_ID = Object_ID(N''myMOCK_DATA''))
BEGIN
alter table myMOCK_DATA add NS_'+@plantype +' integer
END'
print @script;exec(@script)
set @script='IF not EXISTS(SELECT 1 FROM sys.columns
WHERE Name = ''AS_'+@plantype + ''' AND Object_ID = Object_ID(N''myMOCK_DATA''))
BEGIN
alter table myMOCK_DATA add AS_'+@plantype +' integer
END'
print @script;exec(@script)
set @script='update myMOCK_DATA set NS_'+@plantype+'='+convert(varchar(10),@m_ns)+ ' where tid='''+@tid+''''
print @script;exec(@script)
set @script='update myMOCK_DATA set AS_'+@plantype+'='+convert(varchar(10),@m_as)+ ' where tid='''+@tid+''''
print @script;exec(@script)
fetch mycursor into @tid,@plantype,@m_ns,@m_as
end
close mycursor
deallocate mycursor
select * from myMOCK_DATA
尝试只选择需要的列来生成 header:
SELECT [1]
, [2]
, [3]
, [4]
, [5]
FROM (SELECT klassID, KlassText FROM tblKlass) s
PIVOT (
MAX(KlassText)
FOR klassID IN ([1], [2], [3], [4], [5])
) p
我正在尝试在 SQL 中创建一个枢轴 table。我的结果并没有像我希望的那样被合并到每个 TID 的一行中。这个例子应该清楚我的问题:
Results:
TID NS_AM AS_AM NS_DB AS_DB
TID 1a 971 947
TID 2 807 974
TID 1a 954 910
TID 2 931 904
Desired Results:
TID NS_AM AS_AM NS_DB AS_DB
TID 1a 971 947 954 910
TID 2 807 974 931 904
编辑:这是从大型动态查询派生的。我无法输入该查询,因为它会使问题变得非常混乱。我必须使用 pivot/unpivot。
如有任何帮助,我们将不胜感激。下面是示例数据和生成我的结果的查询。
如您所见,AM 项目被合并到一行,DB 项目被合并到一行,但它们并没有像我希望的那样报告所有结果。
drop table if exists mock_data;
create table MOCK_DATA (
tid VARCHAR(50),
plantype VARCHAR(50),
ns VARCHAR(50),
[as] VARCHAR(50)
);
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '112', '048');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '142', '889');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '887', '668');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '093', '910');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '954', '266');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'DB', '822', '201');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '234', '083');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '527', '716');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '662', '168');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '795', '947');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '971', '588');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '755', '234');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '199', '603');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '164', '362');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '943', '462');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '971', '164');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '594', '822');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '467', '478');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '064', '591');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 1a', 'AM', '639', '298');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '186', '797');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '226', '369');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '036', '272');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '807', '197');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '167', '402');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '477', '047');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '262', '974');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '268', '282');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'AM', '508', '069');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '303', '528');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '747', '325');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '293', '614');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '886', '221');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '652', '365');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '931', '904');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '089', '662');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '922', '497');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '722', '328');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '386', '324');
insert into MOCK_DATA (tid, plantype, ns, [as]) values ('TID 2', 'DB', '402', '552');
SELECT [TID],
IsNull([NS_AM], '') AS [NS_AM],
IsNull([AS_AM], '') AS [AS_AM]
FROM
(
SELECT [TID],
[PlanType],
col+'_'+CAST(PlanType AS VARCHAR(50)) col,
value
FROM
(
SELECT PlanType,
[TID],
CAST(NS AS VARCHAR(100)) AS NS,
CAST(AS AS VARCHAR(100)) AS AS
FROM #temp
) s UNPIVOT(value FOR col IN(NS,
AS )) unpiv
) src PIVOT(MAX(value) FOR col IN([NS_AM],
[AS_AM],
[NS_DB],
[AS_DB]
)) p;
在此先感谢您。
Null 被用作替代品(作为一些缺失值的一些大随机数)这就是为什么它也如此独特。但是这里作为聚合函数确实会忽略空值,除了按照标准计数,尽管您也可以同时使用 min 和 max
进行检查如果根据我的假设只有空值与上述不同
,您可以使用group by
并取 min/max
Select TID, min(NS_AM), min( AS_AM),
min(NS_DB), min(AS_DB) Group by
TID.
使用 CROSS TABS 而不是取消和旋转数据,这可能会非常简单。
SELECT TID,
MAX( CASE WHEN PlanType = 'AM' THEN [ns] END) AS NS_AM,
MAX( CASE WHEN PlanType = 'AM' THEN [as] END) AS AS_AM,
MAX( CASE WHEN PlanType = 'DB' THEN [ns] END) AS NS_DB,
MAX( CASE WHEN PlanType = 'DB' THEN [as] END) AS AS_DB
FROM MOCK_DATA
GROUP BY TID;
如果你想使用动态代码,转换起来并不难。这只是您需要处理的每一列的复制粘贴编辑问题,代码将根据需要为 plantype 添加尽可能多的值。
DECLARE @SQL nvarchar(MAX)
SELECT @SQL = N'SELECT TID' + CHAR(10)
+ ( SELECT DISTINCT REPLACE( REPLACE(
CHAR(9) + ',MAX( CASE WHEN PlanType = <<quotedplantype>> THEN [ns] END) AS NS_<<plantype>>' + CHAR(10)
+ CHAR(9) + ',MAX( CASE WHEN PlanType = <<quotedplantype>> THEN [as] END) AS AS_<<plantype>>' + CHAR(10)
, '<<quotedplantype>>', QUOTENAME(plantype, '''')), '<<plantype>>', plantype)
FROM MOCK_DATA
FOR XML PATH(''), TYPE).value('./text()[1]', 'varchar(max)') +
+ N'FROM MOCK_DATA' + NCHAR(10)
+ N'GROUP BY TID;'
EXEC sp_executesql @SQL /*, @params_def, @param1, @param2,..., @paramN*/;
尝试将 "Order by TID" 添加到您的 PIVOT/UNPIVOT 表达式中。
您可以通过如下方式进行内部联接来获取所需的数据,无需数据透视!
select v1.tid,v1.m_ns[Ns_Am],v1.m_as[As_Am],v2.m_ns[NS_DB],V2.m_As[AS_DB] from(
select tid,plantype,max(ns)[m_ns],max([as]) [m_as] from MOCK_DATA group by tid,plantype) v1
inner join
(select tid,plantype,max(ns)[m_ns],max([as]) [m_as] from MOCK_DATA group by tid,plantype)v2
on v1.tid=v2.tid and v1.plantype='Am' and v2.plantype='DB'
你也可以使用这个你可以动态化的脚本(给我一些时间,我会为你做!)
select v1.tid,v1.[am] [ns_am],v1.[db][ns_db],v2.[am] [as_am],v2.[db][as_db] from
(select * from(
select tid,ns,[PlanType] from MOCK_DATA) s
pivot
(max(ns) for [PlanType] in ([AM],[DB]) )s
) v1
inner join
(
select * from(
select tid,[as],[PlanType] from MOCK_DATA) s
pivot
(max([as]) for [PlanType] in ([AM],[DB]) )s) v2
on v1.tid=v2.tid
这是承诺的动态解决方案,使用游标,而不是连接 它动态地将列添加到最终 table 并更新游标循环内的数据
IF EXISTS(SELECT 1 FROM sysobjects where name='myMOCK_DATA') drop table myMOCK_DATA
create table myMOCK_DATA (tid varchar(10));insert into myMOCK_DATA(tid) select distinct(tid) from MOCK_DATA
declare mycursor cursor for
select tid,plantype,max(ns)[m_ns],max([as])[m_as] from MOCK_DATA group by tid,plantype
declare @plantype as varchar(2);declare @tid as varchar(10);declare @m_ns as int;declare @m_as as int
declare @script as varchar(max);open mycursor
fetch mycursor into @tid,@plantype,@m_ns,@m_as
while @@fetch_status=0
begin
set @script='IF not EXISTS(SELECT 1 FROM sys.columns WHERE Name = ''NS_'+@plantype +''' AND Object_ID = Object_ID(N''myMOCK_DATA''))
BEGIN
alter table myMOCK_DATA add NS_'+@plantype +' integer
END'
print @script;exec(@script)
set @script='IF not EXISTS(SELECT 1 FROM sys.columns
WHERE Name = ''AS_'+@plantype + ''' AND Object_ID = Object_ID(N''myMOCK_DATA''))
BEGIN
alter table myMOCK_DATA add AS_'+@plantype +' integer
END'
print @script;exec(@script)
set @script='update myMOCK_DATA set NS_'+@plantype+'='+convert(varchar(10),@m_ns)+ ' where tid='''+@tid+''''
print @script;exec(@script)
set @script='update myMOCK_DATA set AS_'+@plantype+'='+convert(varchar(10),@m_as)+ ' where tid='''+@tid+''''
print @script;exec(@script)
fetch mycursor into @tid,@plantype,@m_ns,@m_as
end
close mycursor
deallocate mycursor
select * from myMOCK_DATA
尝试只选择需要的列来生成 header:
SELECT [1]
, [2]
, [3]
, [4]
, [5]
FROM (SELECT klassID, KlassText FROM tblKlass) s
PIVOT (
MAX(KlassText)
FOR klassID IN ([1], [2], [3], [4], [5])
) p