如何在不使用临时表或视图的情况下在多个列上使用 PIVOT [重复]
Posted
技术标签:
【中文标题】如何在不使用临时表或视图的情况下在多个列上使用 PIVOT [重复]【英文标题】:How to use PIVOT on multiple columns without using temp table or views [duplicate] 【发布时间】:2019-06-20 16:50:16 【问题描述】:我在 Microsoft SQL Server 2016 上并且有 3 个表:
CREATE TABLE [dbo].[n](
[ID] [int] NOT NULL,
[IP] [nvarchar](50) NULL,
[C] [nvarchar](255) NULL,
CONSTRAINT [PK_N] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
);
INSERT INTO n VALUES
(20005, '12.34.567.890', 'TEXT02'),
(20033, '90.87.654.32', 'TEXT01');
SELECT * FROM n;
CREATE TABLE [dbo].[v](
[ID] [int] NOT NULL,
[VID] [int] NOT NULL,
[C] [nvarchar](75) NULL,
[VT] [nvarchar](40) NULL,
[VSU] [float] NULL,
[VSA] [float] NULL,
[VS] [float] NULL,
CONSTRAINT [V_PK] PRIMARY KEY CLUSTERED
(
[ID] ASC,
[VID] ASC
)
);
INSERT INTO v VALUES
(20005, 87748, 'Physical Memory', 'RAM', 7213740032, 9918472192, 17132212224),
(20005, 87749, 'Virtual Memory', 'Virtual Memory', 5319143424, 28943335424, 34262478848),
(20005, 87750, 'C:\ Label: 5C97F', 'Fixed Disk', 67721424896, 78335770624, 146057195520),
(20005, 87751, 'D:\ Label:Vo2 9C909', 'Fixed Disk', 13425840185344, 1574196776960, 15000036962304),
(20005, 87752, 'E:\ Label:Vi1 651E', 'Fixed Disk', 13427242958848, 1572793942016, 15000036900864),
(20033, 87885, 'Physical Memory', 'RAM', 2359943168, 10511417344, 12871360512),
(20033, 87886, 'Virtual Memory', 'Virtual Memory', 3684294656, 22056480768, 25740775424),
(20033, 87887, 'C:\ Label: 854E3', 'Fixed Disk', 69951520768, 229381271552, 299332792320),
(20033, 87888, 'D:\ Label:Vio EA629', 'Fixed Disk', 9679718285312, 12318431010816, 21998149296128);
SELECT * FROM v;
CREATE TABLE [dbo].[ncp](
[ID] [int] NOT NULL,
[MA] [nvarchar](400) NULL,
CONSTRAINT [PK_NCP] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
);
INSERT INTO ncp VALUES
(20005, 'APPNAME'),
(20033, 'APPNAME');
SELECT * FROM ncp;
我想要得到的是每个 n.C 都有一行包含所有详细信息,例如 v.C、v.VS、v.VSU 和 v.VSA
我尝试了什么 1:我已经编写了获取 v.C 的部分,它按预期工作。我想出的 SQL:
SELECT *
FROM (
SELECT n.C AS [Device],
v.C AS [Volume],
'Volume' + cast(row_number() over (PARTITION BY n.C ORDER BY (select 1)) as varchar(4)) as dupVolume
FROM n n
JOIN v v
ON v.ID = n.ID
JOIN ncp ncp
ON ncp.ID = n.ID
WHERE ncp.MA LIKE '%APPNAME%'
AND (v.VT LIKE 'fixed%' OR v.VT LIKE 'mount%' OR v.VT LIKE 'network%')
) T
PIVOT (
MAX(Volume) FOR dupVolume IN ([Volume1],[Volume2],[Volume3])
) P1;
结果如下:
当我尝试添加 v.VS 时,我得到超过 2 行。
我尝试了 2:这就是我尝试的方式:
SELECT *
FROM (
SELECT n.C AS [Device],
v.C AS [Volume],
v.VS AS [VolumeSize],
'Volume' + cast(row_number() over (PARTITION BY n.C ORDER BY (select 1)) as varchar(4)) as dupVolume,
'VolumeSize' + cast(row_number() over (PARTITION BY n.C ORDER BY (select 1)) as varchar(4)) as dupVolumeSize
FROM n n
JOIN v v
ON v.ID = n.ID
JOIN ncp ncp
ON ncp.ID = n.ID
WHERE ncp.MA LIKE '%APPNAME%'
AND (v.VT LIKE 'fixed%' OR v.VT LIKE 'mount%' OR v.VT LIKE 'network%')
) T
PIVOT (
MAX(Volume) FOR dupVolume IN ([Volume1],[Volume2],[Volume3])
) P1
PIVOT (
MAX(VolumeSize) FOR dupVolumeSize IN ([VolumeSize1],[VolumeSize2],[VolumeSize3])
) P2;
但它拉了这个:
预期结果:我想要的结果应该是这样的:
这会给我 v.C 和 v.VS。稍后我也想获得 v.VSU 和 v.VSA。将为每个 v.VSU(VSU1、VSU2、VSU3)和 v.VSA(VSA1、VSA2、VSA3)添加三个新列。
问题:我怎样才能得到预期的结果?我什至需要为此支点?
我可以灵活地使用任何纯 SQL 方法,只要它能得到我预期的结果,但我不能使用临时表或视图,因为此 SQL 将被提供给工具。该工具无权在数据库中创建临时表或视图。
【问题讨论】:
我认为我的问题与上述问题不同。我必须从 3 个表中获取数据。我更新了我的问题,提到我不能使用视图或临时表。并且提到的问题甚至没有完整的解决方案。这只是一个提示,我无法在我的情况下使用。 该副本中的第二个答案可以满足您的需要 好的。至少我无法弄清楚如何使用标记重复问题中的答案 2 在我的情况下工作。特别是当数据不是在单个表中而是在三个不同的表中时。我最终重用了我发布的 SQL 并将其加入以获得所需的结果。所以我很好。感谢大家的帮助。由于此问题已关闭,因此我无法在此处发布最终版本的 SQL。如果有人想知道我用了什么,请给我发消息,我会回复(如果可能的话)。 【参考方案1】:我认为这就是你所需要的。
SELECT *
INTO SRC
FROM (
SELECT N.C AS NC, V.C AS VC, ' VOLUME' + cast(row_number() OVER (
PARTITION BY N.C ORDER BY V.C
) AS VARCHAR) AS COL
FROM V
INNER JOIN N
ON (V.ID = N.ID)
WHERE V.VT = 'Fixed Disk'
UNION
SELECT N.C, CAST(CASE
WHEN VSU >= VSA
AND VSU >= VS
THEN VSU
WHEN VSA >= VSU
AND VSA >= VS
THEN VSA
WHEN VS >= VSU
AND VS >= VSA
THEN VS
ELSE VSU
END AS VARCHAR) AS vol, 'VOLUMESIZE' + cast(row_number() OVER (
PARTITION BY N.C ORDER BY VSU
) AS VARCHAR)
FROM V
INNER JOIN N
ON (V.ID = N.ID)
WHERE V.VT = 'Fixed Disk'
) A
然后在简单的旋转之后。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(COL)
from SRC
GROUP BY COL
order by 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT NC AS DEVICE ,' + @cols + ' from
(
select *
from SRC
) x
pivot
(
max(VC)
for COL in (' + @cols + ')
) p '
execute(@query);
【讨论】:
嗨@kiran gadhe。谢谢您的答复。我尝试使用它,但它有多个语法错误。我试图删除那些但无法让 SQL 工作。 已修改脚本以消除语法错误。以上是关于如何在不使用临时表或视图的情况下在多个列上使用 PIVOT [重复]的主要内容,如果未能解决你的问题,请参考以下文章