简体   繁体   English

SQL-将列转置为行

[英]SQL - Transpose a Column to Row

Ok, I've searched but can't find anything as specific as I'm trying to do here. 好的,我已经搜索了,但是找不到像我在这里尝试的那样具体的东西。 I have two different tables that I need info from. 我有两个不同的表,需要这些信息。 This is a sample schema - similar to what I'm working from: 这是一个示例架构-与我正在工作的类似:

create table Nodes(
  Caption varchar(max),
  IP_Address varchar(max),
  NodeID varchar(max)
);

insert into Nodes (Caption, IP_Address, NodeID)
values ('dev-srvr', '10.0.0.1', '29023');
insert into Nodes (Caption, IP_Address, NodeID)
values ('prod-srvr', '10.0.2.1', '29056');
insert into Nodes (Caption, IP_Address, NodeID)
values ('test-srvr', '10.1.1.1', '29087');

create table Volumes(
  Caption varchar(max),
  NodeID varchar(max)
);

insert into Volumes (NodeID, Caption)
values ('29023', '/');
insert into Volumes (NodeID, Caption)
values ('29023', '/boot');
insert into Volumes (NodeID, Caption)
values ('29023', '/dev/shm');
insert into Volumes (NodeID, Caption)
values ('29023', '/home');
insert into Volumes (NodeID, Caption)
values ('29056', '/');
insert into Volumes (NodeID, Caption)
values ('29056', '/var');
insert into Volumes (NodeID, Caption)
values ('29056', '/opt');
insert into Volumes (NodeID, Caption)
values ('29087', '/tmp');

I'm attempting to write a query (with a where clause...will have multiple a filters on final version) that will return Node.Caption, IP_Address, and every Volumes.Caption associated (based on NodeID). 我正在尝试编写一个查询(带有where子句...在最终版本上将具有多个过滤器),该查询将返回Node.Caption,IP_Address和每个关联的Volumes.Caption(基于NodeID)。 The number of entries in Volumes.Caption for each NodeID is dynamic and varies from 1 to about 60 or so. 每个节点ID的Volumes.Caption中的条目数是动态的,范围从1到大约60左右。 All I know how to write is this: 我所知道的是这样写的:

select Nodes.Caption, Nodes.IP_Address, Volumes.Caption as Volume
from Nodes with (nolock)
inner join Volumes
on Nodes.NodeID=Volumes.NodeID
where IP_Address like '10.0%'

Which returns the following: 返回以下内容:

Caption   | IP_Address | Volume
---------------------------------
dev-srvr  | 10.0.0.1   | /
dev-srvr  | 10.0.0.1   | /boot
dev-srvr  | 10.0.0.1   | /dev/shm
dev-srvr  | 10.0.0.1   | /home
prod-srvr | 10.0.0.1   | /var
prod-srvr | 10.0.0.1   | /opt

But what I need is a single ROW per NodeID showing Node.Caption, IP_Address and all matching Volumes if possible. 但是我需要的是每个NodeID有一个ROW,显示Node.Caption,IP_Address和所有匹配的卷(如果可能)。 Like this (the final column names are not important...can be anything): 像这样(最后一列的名称并不重要...可以是任何东西):

Caption   | IP_Address | Volume1 | Volume2 | Volume3  | Volume 4
----------------------------------------------------------------
dev-srvr  | 10.0.0.1   | /       | /boot   | /dev/shm | /home
prod-srvr | 10.0.0.1   | /var    | /opt

There's 100 pivot examples on SO so I wanted to show a way that you could do this, which isn't as good as pivot, but works for your instance. SO上有100个枢轴示例,因此我想展示一种可以实现此目的的方法,虽然不如枢轴好,但适用于您的实例。 It may not fit your entire dataset and was based on your sample data only. 它可能不适合您的整个数据集,并且仅基于样本数据。

Of note, your test data doesn't provide the results you claim they do. 值得注意的是,您的测试数据无法提供您声称的结果。 Probably just a typo on the insert. 可能只是插入内容上的错字。

create table #Nodes(
  Caption varchar(max),
  IP_Address varchar(max),
  NodeID varchar(max)
);

insert into #Nodes (Caption, IP_Address, NodeID)
values 
('dev-srvr', '10.0.0.1', '29023'),
('prod-srvr', '10.0.2.1', '29056'),
('test-srvr', '10.1.1.1', '29087');

create table #Volumes(
  Caption varchar(max),
  NodeID varchar(max)
);

insert into #Volumes (NodeID, Caption)
values 
 ('29023', '/'),
 ('29023', '/boot'),
 ('29023', '/dev/shm'),
 ('29023', '/home'),
 ('29056', '/'),
 ('29056', '/var'),
 ('29056', '/opt'),
 ('29087', '/tmp');


select 
    n.Caption, 
    n.IP_Address, 
    v.Caption as Volume
from #Nodes n
inner join #Volumes v
on n.NodeID=v.NodeID
where IP_Address like '10.0%'

;with cte as(
select 
    n.Caption, 
    n.IP_Address, 
    v.Caption as Volume,
    ROW_NUMBER() over (partition by n.caption, IP_Address order by n.caption) as RN
from #Nodes n
inner join #Volumes v
on n.NodeID=v.NodeID
where IP_Address like '10.0%')

select
    x.caption,
    x.IP_Address,
    max(Volume1) as Volume1,
    max(Volume2) as Volume2,
    max(Volume3) as Volume3,
    max(Volume4) as Volume4
from(
    select
        Caption,
        IP_Address,
        case when RN = 1 then Volume end as Volume1,
        case when RN = 2 then Volume end as Volume2,
        case when RN = 3 then Volume end as Volume3,
        case when RN = 4 then Volume end as Volume4
    from cte) x
group by x.Caption, x.IP_Address


drop table #Nodes
drop table #Volumes

USING DYNAMIC PIVOT 使用动态PIVOT

create table #Nodes(
  Caption varchar(max),
  IP_Address varchar(max),
  NodeID varchar(max)
);

insert into #Nodes (Caption, IP_Address, NodeID)
values 
('dev-srvr', '10.0.0.1', '29023'),
('prod-srvr', '10.0.2.1', '29056'),
('test-srvr', '10.1.1.1', '29087');

create table #Volumes(
  Caption varchar(max),
  NodeID varchar(max)
);

insert into #Volumes (NodeID, Caption)
values 
 ('29023', '/'),
 ('29023', '/boot'),
 ('29023', '/dev/shm'),
 ('29023', '/home'),
 ('29056', '/'),
 ('29056', '/var'),
 ('29056', '/opt'),
 ('29087', '/tmp');



DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)


select 
    n.Caption, 
    n.IP_Address, 
    v.Caption as Volume,
    'Volume' + cast(ROW_NUMBER() over (partition by n.caption, IP_Address order by n.caption) as varchar(16)) as Cname
    --ROW_NUMBER() over (partition by n.caption, IP_Address order by n.caption) as RN
into #staging
from #Nodes n
inner join #Volumes v
on n.NodeID=v.NodeID
where IP_Address like '10.0%'




--Get distinct values of the PIVOT Column 
SELECT @ColumnName= ISNULL(@ColumnName + ',','') 
       + QUOTENAME(Cname)
FROM (SELECT DISTINCT Cname FROM #staging) AS Cname

--Prepare the PIVOT query using the dynamic 
SET @DynamicPivotQuery = 
  N'SELECT Caption, IP_Address, ' + @ColumnName + '
    FROM #staging
    PIVOT(MAX(Volume) 
          FOR Cname IN (' + @ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql @DynamicPivotQuery



drop table #Nodes
drop table #Volumes
drop table #staging

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM