2017-03-11 37 views
1

我的表:SQL Server以多行合併成一行,其中COL0 = COL1

previousid|CurrentID|Data 
| 1  | 2  | Data 1 
| 2  | 3  | Data 2 
| 3  | 4  | Data 3 
| 4  | 5  | Data 4 

結果,我去找:

Select .... where PreviousID=1 : 

    |Col0|Col1|Col2 |Col3|Col 4|Col5| Col6 | Col7 | Col8 
    |1 |2 |Data 1|3 |Data 2| 4 | data 3| 5 | data 4 

Select .....where PreviousID=2 

    |Col0|Col1|Col2 |Col3|Col 4|Col5| Col6 | 
    |2 |3 |Data 2|4 |Data 3| 5 | data 4| 

我試圖創造一些SQL服務器查詢來獲取結果和沒有運氣,請幫助我的傢伙

+0

即會導致不確定的列數,你不應該瞄準。 但是,你應該看看遞歸查詢:https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx – Pinx0

+0

而如果你有1000行?那你期望1000列嗎? –

+0

是否有任何可能的方法來實現這一點?,我打算限制Previousid和cuurentid之間的連接到10,soo max列是10行1 –

回答

0

我們可以在幾個步驟做到這一點:

  1. 聲明並設置一個變量來使用我們的根節點,並創建一個臨時表來存儲來自我們recusive查詢的結果:
  2. 將結果從recusive查詢插入臨時表
  3. 生成並執行動態sql到pivot()臨時表。
  4. (候補)生成並執行動態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'); 
  1. 聲明並設置一個變量爲使用我們的根節點,並創建一個臨時表,用於存儲從我們的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 | 
    +------+------+--------+------+--------+------+--------+