Zul*_*u Z 4 sql-server pivot sql-server-2012
我有查询返回客户贷款与相关的抵押品名称,如下面(1)但我想连续只有一个不同的贷款编号和旁边的名称,如同其他例子(2).一直在玩旋转,但无法解决,因为我没有汇总列,我不知道有多少贷款数字,我将得到每笔贷款可能有多少抵押品.怎么做???可能在SQL Server 2012中?
谢谢
(1)
loanid|name |Address |
1 |John |New York|
1 |Carl |New York|
1 |Henry |Boston |
2 |Robert|Chicago |
3 |Joanne|LA |
3 |Chris |LA |
Run Code Online (Sandbox Code Playgroud)
(2)我需要这样的东西
loanid|name |address |name |address |name|address|
1 |Jonh |New York |Carl |New York|Henry|Boston|
2 |Robert|Chicago |
3 |Joanne|LA |Chris|LA|
Run Code Online (Sandbox Code Playgroud)
Tar*_*ryn 13
虽然M.Ali的答案可以为您提供结果,但由于您使用的是SQL Server 2012,我会将这些name和address列略有不同以获得最终结果.
由于您使用的是SQL Server 2012,因此可以使用CROSS APPLYwith VALUES将这些多列拆分为多行.但在你这样做之前,我会用你row_number()来获得你将拥有的新列的总数.
使用CROSS APPLY"UNPIVOT"数据的代码如下所示:
select d.loanid,
col = c.col + cast(seq as varchar(10)),
c.value
from
(
select loanid, name, address,
row_number() over(partition by loanid
order by loanid) seq
from yourtable
) d
cross apply
(
values
('name', name),
('address', address)
) c(col, value);
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.这将使您的数据格式类似于:
| LOANID | COL | VALUE |
|--------|----------|----------|
| 1 | name1 | John |
| 1 | address1 | New York |
| 1 | name2 | Carl |
| 1 | address2 | New York |
| 1 | name3 | Henry |
| 1 | address3 | Boston |
Run Code Online (Sandbox Code Playgroud)
您现在拥有一个COL包含所有新列名称的列,并且关联的值也位于单个列中.现在,新列名称的末尾有一个数字(1,2,3等),具体取决于每个条目的总条目数loanid.现在你可以申请PIVOT:
select loanid,
name1, address1, name2, address2,
name3, address3
from
(
select d.loanid,
col = c.col + cast(seq as varchar(10)),
c.value
from
(
select loanid, name, address,
row_number() over(partition by loanid
order by loanid) seq
from yourtable
) d
cross apply
(
values
('name', name),
('address', address)
) c(col, value)
) src
pivot
(
max(value)
for col in (name1, address1, name2, address2,
name3, address3)
) piv;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.最后,如果你不知道有多少对Name和Address你将有那么你可以使用动态SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(seq as varchar(10)))
from
(
select row_number() over(partition by loanid
order by loanid) seq
from yourtable
) d
cross apply
(
select 'Name', 1 union all
select 'Address', 2
) c (col, so)
group by seq, col, so
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT loanid,' + @cols + '
from
(
select d.loanid,
col = c.col + cast(seq as varchar(10)),
c.value
from
(
select loanid, name, address,
row_number() over(partition by loanid
order by loanid) seq
from yourtable
) d
cross apply
(
values
(''name'', name),
(''address'', address)
) c(col, value)
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p '
exec sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.两个版本都给出了结果:
| LOANID | NAME1 | ADDRESS1 | NAME2 | ADDRESS2 | NAME3 | ADDRESS3 |
|--------|--------|----------|--------|----------|--------|----------|
| 1 | John | New York | Carl | New York | Henry | Boston |
| 2 | Robert | Chicago | (null) | (null) | (null) | (null) |
| 3 | Joanne | LA | Chris | LA | (null) | (null) |
Run Code Online (Sandbox Code Playgroud)
测试数据
DECLARE @TABLE TABLE (loanid INT,name VARCHAR(20),[Address] VARCHAR(20))
INSERT INTO @TABLE VALUES
(1,'John','New York'),(1,'Carl','New York'),(1,'Henry','Boston'),
(2,'Robert','Chicago'),(3,'Joanne','LA'),(3,'Chris','LA')
Run Code Online (Sandbox Code Playgroud)
询问
SELECT loanid
,ISNULL(name1, '') AS name1
,ISNULL(Address1, '') AS Address1
,ISNULL(name2, '') AS name2
,ISNULL(Address2, '') AS Address2
,ISNULL(name3, '') AS name3
,ISNULL(Address3, '') AS Address3
FROM (
SELECT loanid
,'name' + CAST(ROW_NUMBER() OVER (PARTITION BY loanid ORDER BY loanid) AS NVARCHAR(10)) AS Cols
, name AS Vals
FROM @TABLE
UNION ALL
SELECT loanid
,'Address' + CAST(ROW_NUMBER() OVER (PARTITION BY loanid ORDER BY loanid) AS NVARCHAR(10))
, [Address]
FROM @TABLE ) t
PIVOT (MAX(Vals)
FOR Cols
IN (name1, Address1,name2,Address2,name3,Address3)
)P
Run Code Online (Sandbox Code Playgroud)
结果集
????????????????????????????????????????????????????????????????????
? loanid ? name1 ? Address1 ? name2 ? Address2 ? name3 ? Address3 ?
????????????????????????????????????????????????????????????????????
? 1 ? John ? New York ? Carl ? New York ? Henry ? Boston ?
? 2 ? Robert ? Chicago ? ? ? ? ?
? 3 ? Joanne ? LA ? Chris ? LA ? ? ?
????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
动态列的更新
DECLARE @Cols NVARCHAR(MAX);
SELECT @Cols = STUFF((
SELECT DISTINCT ', ' + QUOTENAME(Cols)
FROM (
SELECT loanid
,'name' + CAST(ROW_NUMBER() OVER (PARTITION BY loanid ORDER BY loanid) AS NVARCHAR(10)) AS Cols
, name AS Vals
FROM @TABLE
UNION ALL
SELECT loanid
,'Address' + CAST(ROW_NUMBER() OVER (PARTITION BY loanid ORDER BY loanid) AS NVARCHAR(10))
, [Address]
FROM @TABLE ) t
GROUP BY QUOTENAME(Cols)
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
DECLARE @Sql NVARCHAR(MAX);
SET @Sql = 'SELECT ' + @Cols + '
FROM (
SELECT loanid
,''name'' + CAST(ROW_NUMBER() OVER
(PARTITION BY loanid ORDER BY loanid) AS NVARCHAR(10)) AS Cols
, name AS Vals
FROM @TABLE
UNION ALL
SELECT loanid
,''Address'' + CAST(ROW_NUMBER() OVER
(PARTITION BY loanid ORDER BY loanid) AS NVARCHAR(10))
, [Address]
FROM @TABLE ) t
PIVOT (MAX(Vals)
FOR Cols
IN (' + @Cols + ')
)P'
EXECUTE sp_executesql @Sql
Run Code Online (Sandbox Code Playgroud)
注意
这对我的答案中的给定样本数据无效,因为它使用表变量,因为它有自己的范围,所以它对动态sql不可见.但是这个解决方案可以在普通的sql server表上运行.
选择列的顺序也会略有不同.