如何在不使用临时表或视图的情况下在多个列上使用 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 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用临时文件的情况下在 python 的 tarfile 中写入大量数据

如何在不改变其位置的情况下在界面生成器中将子视图置于前面

特定列上的SQL内部联接

如何在不使用对话框的情况下在操作栏上方显示视图?

如何在不使用 segue 的情况下在视图控制器之间传递图像

BI Answers/OBIEE- 在不影响行结果的情况下在列上创建过滤器