我有查询返回客户贷款及相关的抵押品名称如下(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 |
(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|
答案 0 :(得分:12)
虽然M.Ali's answer会为您提供结果,但由于您使用的是SQL Server 2012,因此我会将name
和address
列略微不同,以获得最终结果。
由于您使用的是SQL Server 2012,因此可以将CROSS APPLY
与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);
见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 |
现在,您有一个列COL
,其中包含所有新列名称,并且关联的值也位于单个列中。根据每loanid
个条目总数,新列名称最后会有一个数字(1,2,3等)。现在你可以申请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;
见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;
见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) |
答案 1 :(得分:7)
测试数据
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')
<强>查询强>
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
结果集
╔════════╦════════╦══════════╦═══════╦══════════╦═══════╦══════════╗
║ loanid ║ name1 ║ Address1 ║ name2 ║ Address2 ║ name3 ║ Address3 ║
╠════════╬════════╬══════════╬═══════╬══════════╬═══════╬══════════╣
║ 1 ║ John ║ New York ║ Carl ║ New York ║ Henry ║ Boston ║
║ 2 ║ Robert ║ Chicago ║ ║ ║ ║ ║
║ 3 ║ Joanne ║ LA ║ Chris ║ LA ║ ║ ║
╚════════╩════════╩══════════╩═══════╩══════════╩═══════╩══════════╝
动态列更新
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
注意的
这对我的答案中的给定样本数据无效,因为它使用表变量,因为它具有自己的作用域,所以它对动态sql不可见。但是这个解决方案可以在普通的sql server表上运行。
此外,选择列的顺序也会略有不同。
答案 2 :(得分:0)
SELECT DISTINCT
loanid
,STUFF((SELECT DISTINCT ',' + name +' ('+address+')'
FROM table a
WHERE a.loanid = b.loanid
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
FROM table b
这会放
loanid | name(address)
1 | name (address),name2 (address2),name3........
2 | name (address),name2 (address2),name3........
3 | name (address),name2 (address2),name3........