2012-07-19 28 views
1

我有一個表:逗號分隔一列的結果以顯示在另一列旁邊?

lease_id,suite_id

租賃是一個關鍵,你可以有多個套件的一個租約。我試圖創建一個查詢,顯示我所有的套件是一個租賃的關聯,基本上和以下的輸出:

lease_id:1 suite_list:A1,A2,B1

不幸的是,我不確定如何處理這個問題(甚至如何開始),因爲這對我來說是一種新的問題...任何幫助將不勝感激!

+0

可能的重複 - http://stackoverflow.com/questions/194852/concatenate-many-rows-into-a-single-text-string – vmvadivel 2012-07-19 03:11:41

+0

@vmvadivel除了不,請完整閱讀我的問題/看到我發佈的答案最終解決方案 – Codingo 2012-07-19 03:19:40

回答

1

您可以使用FOR XML。

該代碼將是這樣的:

-- Sample data tables 
select * 
into #leases 
from (
    select '1' as lease_id 
    union 
    select '2' as lease_id 
    ) a 

select * 
into #leaseSuites 
from (
    select '1' as lease_id, 
     'A1' as suite_id 
    union 
    select '1' as lease_id, 
     'A2' as suite_id 
    union 
    select '1' as lease_id, 
     'B1' as suite_id 
    union 
    select '2' as lease_id, 
     'C2' as suite_id 
    union 
    select '2' as lease_id, 
     'B3' as suite_id   
    ) a 


-- Creates comma delimited with child table. 
select left(suite_list, LEN(suite_list) - 1) as suite_list 
from (
    SELECT 'lease_id: ' + lease_id + ' ' + 
     'suite_list: ' + (
     SELECT s.suite_id + ',' 
     FROM #leaseSuites s 
     WHERE l.lease_id = s.lease_id 
     ORDER BY s.suite_id 
     FOR XML PATH('') 
    ) AS suite_list 
    FROM #leases l) a 

點擊here看到一篇文章用一個例子。

+1

謝謝,我用這個作爲我的第二種方法,因爲我的原始思路有點慢。不勝感激! – Codingo 2012-07-19 03:21:35

1

我假設你的表叫做LeasedSuites。

我們需要一個功能:

 create function dbo.AllSuite (@l int) returns varchar(100) 
    as begin 
     declare @v varchar(2); 
     declare @r varchar(100); 

     DECLARE sc CURSOR FOR select suite_id from LeasedSuites where lease_id = @l 
     OPEN sc 
     FETCH NEXT FROM sc INTO @v 
     WHILE @@FETCH_STATUS = 0 BEGIN 
     select @r = @r + ',' + @v; 
     FETCH NEXT FROM sc INTO @v 
     END 
     CLOSE sc 
     DEALLOCATE sc 

     return substring(@r, 2, len(@r) - 1); 
    end 

和查詢:

 declare @l int; 

    create table #out (lease_id int, suite_str varchar(100) null) 
    insert #out (lease_id) select distinct lease_id from LeasedSuites 

    while (select count(*) from #out where suite_str is null) > 0 begin 
     select @l = min(lease_id) from #out where suite_str is null; 
     update #out set suite_str = dbo.AllSuite(@l) where lease_id = @l; 
    end 

    select 'Lease ID: ' + cast(lease_id as varchar(3)) + ' Suites: ' + suite_str from #out order by l; 

希望這有助於。問候JB

如果這代表一個答案,請標記爲答案。

+0

這可行,但不是很流暢或易於維護。 Upvote都一樣,但我認爲有很多更好的方法來處理這個問題(請參閱其他答案) – Codingo 2012-07-19 03:58:35

1

我已經結束瞭解決這個問題的兩種方式。我的第一個方法,這是不幸的是相當緩慢是:

declare @period_id integer = 
       (
        select period_id 
        from property.period 
        where getdate() between period_start and period_end 
       ) 



;with cte_data as 
(
    select lp.* 
    from property.lease_period lp 
    where period_id = @period_id 
)  
, cte_suites as 
(
    select d.lease_id 
     , (
       select stuff 
       ( 
        ( select ', ' + a.suite_id 
         from 
         ( select a.suite_id 
          from cte_data a 
          where a.lease_id = d.lease_id 
         ) a 
         for xml path('')) 
        , 1, 2, '' 
       ) as suite_list 
      ) suite_list 

    from cte_data d 
    group by d.lease_id 
) , 
cte_count as 
(
    select lease_id , 
      count(suite_id) as 'suites' 
    from property.lease_period 
    where period_id = @period_id 
      and lease_id <> 'No Lease' 
    group by lease_id 

) 
select d.period_id , 
     d.building_id , 
     d.lease_id , 
     s.suite_list 
from cte_data d 
     left outer join cte_suites s 
      on d.lease_id = s.lease_id 
     inner join cte_count c 
      on d.lease_id = c.lease_id 
where period_id = 270 
     and d.lease_id <> 'No Lease' 
     and c.suites > 1 
group by 
     d.period_id , 
     d.building_id , 
     d.lease_id , 
     s.suite_list 

我再剝去了新的發展方向這一回,並重新走近它,從而產生以下(非常非常快):

declare @period_id integer = 
      (
       select period_id 
       from property.period 
       where getdate() between period_start and period_end 
      ) 

;with CteLeaseInMultSuites as 
(
    select period_id, 
      building_id, 
      lease_id 
    from property.lease_period 
    where period_id = @period_id 
      and lease_id <> 'No Lease' 
    group by 
      period_id, 
      building_id, 
      lease_id 
    having count(*) > 1 
) 

select period_id, 
     building_id, 
     lease_id, 
     left(x.suite_list, len(x.suite_list) - 1) as suite_list 
from CteLeaseInMultSuites lm 
     cross apply 
     (
      select suite_id + ', ' 
      from CteLeaseInMultSuites lmx 
        inner join property.lease_period lp 
         on lp.period_id = lmx.period_id 
         and lp.building_id = lmx.building_id 
         and lp.lease_id = lmx.lease_id 
      where lmx.period_id = lm.period_id 
        and lmx.building_id = lm.building_id 
        and lmx.lease_id = lm.lease_id 
      for xml path('') 
     ) x (suite_list)