我們可以在幾個步驟做到這一點:
- 聲明並設置一個變量來使用我們的根節點,並創建一個臨時表來存儲來自我們recusive查詢的結果:
- 將結果從recusive查詢插入臨時表
- 生成並執行動態sql到
pivot()
臨時表。
- (候補)生成並執行動態SQL使用條件聚合代替
pivot()
:
rextester 演示:http://rextester.com/MRFZC75180
測試設置:
create table t (PreviousID int, CurrentID int, Data varchar(32));
insert into t values
(1,2,'Data 1'),(2,3,'Data 2'),(3,4,'Data 3'),(4,5,'Data 4');
- 聲明並設置一個變量爲使用我們的根節點,並創建一個臨時表,用於存儲從我們的recusive查詢的結果:
declare @PreviousId int = 2;
create table #temp (PreviousID int
, Level int
, Col varchar(32)
, Value varchar(32)
, rn int
);
- 插入來自recusive查詢結果到臨時表
個
;with cte as (
select PreviousID, CurrentID, Data, level = 0
from t
where previousId = @PreviousId
union all
select c.PreviousID, c.CurrentID, c.Data, level = p.level +1
from t c
inner join cte as p
on c.PreviousID = p.CurrentID
)
insert into #temp
select p.PreviousId, t.level, x.col, x.value
, rn = row_number() over (order by t.level, x.col)
from cte t
cross apply (
select top 1
PreviousId
from cte i
order by level
) as p (PreviousId)
cross apply (
values ('CurrentId',convert(varchar(32),CurrentId)),('Data',Data)
) as x (col,value);
效果爲止:
+------------+-------+-----------+--------+----+
| PreviousID | Level | Col | Value | rn |
+------------+-------+-----------+--------+----+
| 2 | 0 | CurrentId | 3 | 1 |
| 2 | 0 | Data | Data 2 | 2 |
| 2 | 1 | CurrentId | 4 | 3 |
| 2 | 1 | Data | Data 3 | 4 |
| 2 | 2 | CurrentId | 5 | 5 |
| 2 | 2 | Data | Data 4 | 6 |
+------------+-------+-----------+--------+----+
- 生成並執行動態SQL
pivot()
臨時表。
/* pivot */
declare @cols nvarchar(max);
declare @sql nvarchar(max);
select @cols = stuff((
select
', Col'+convert(nvarchar(10),rn)
from #temp
order by 1
for xml path (''), type).value('.','nvarchar(max)')
,1,1,'')
select @sql ='
select Col0=PreviousID, ' + @cols +'
from (
select PreviousID, Value, rn= ''Col''+convert(nvarchar(10),rn)
from #temp
) as t
pivot (max([Value]) for [rn] in (' + @cols +')) p'
select @sql as CodeGenerated;
exec sp_executesql @sql;
代碼生成:
select Col0=PreviousID, Col1, Col2, Col3, Col4, Col5, Col6
from (
select PreviousID, Value, rn= 'Col'+convert(nvarchar(10),rn)
from #temp
) as t
pivot (max([Value]) for [rn] in (Col1, Col2, Col3, Col4, Col5, Col6)) p
回報:
+------+------+--------+------+--------+------+--------+
| Col0 | Col1 | Col2 | Col3 | Col4 | Col5 | Col6 |
+------+------+--------+------+--------+------+--------+
| 2 | 3 | Data 2 | 4 | Data 3 | 5 | Data 4 |
+------+------+--------+------+--------+------+--------+
- (候補)生成並執行動態SQL使用條件聚合代替
pivot()
:產生
/* conditional aggregation */
--declare @cols nvarchar(max);
--declare @sql nvarchar(max);
select @cols = stuff((
select
char(10)+' , '
+ 'Col'+convert(nvarchar(10),rn)
+' = max(case when rn = '+convert(nvarchar(10),rn)+' then Value end)'
from #temp
order by 1
for xml path (''), type).value('.','nvarchar(max)')
,1,0,'')
select @sql ='
select Col0 = PreviousID'[email protected]+'
from #temp
group by PreviousID'
select @sql as CodeGenerated;
exec sp_executesql @sql;
代碼:
select Col0 = PreviousID
, Col1 = max(case when rn = 1 then Value end)
, Col2 = max(case when rn = 2 then Value end)
, Col3 = max(case when rn = 3 then Value end)
, Col4 = max(case when rn = 4 then Value end)
, Col5 = max(case when rn = 5 then Value end)
, Col6 = max(case when rn = 6 then Value end)
from #temp
group by PreviousID
回報:
+------+------+--------+------+--------+------+--------+
| Col0 | Col1 | Col2 | Col3 | Col4 | Col5 | Col6 |
+------+------+--------+------+--------+------+--------+
| 2 | 3 | Data 2 | 4 | Data 3 | 5 | Data 4 |
+------+------+--------+------+--------+------+--------+
即會導致不確定的列數,你不應該瞄準。 但是,你應該看看遞歸查詢:https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx – Pinx0
而如果你有1000行?那你期望1000列嗎? –
是否有任何可能的方法來實現這一點?,我打算限制Previousid和cuurentid之間的連接到10,soo max列是10行1 –