1

私はテーブルを持っています:

lease_id、suite_id

リースが鍵であり、複数のスイートを 1 つのリースにすることができます。リースが関連付けられているすべてのスイートを表示するクエリを作成しようとしています。基本的には次のような出力です。

lease_id: 1 suite_list: A1、A2、B1

残念ながら、これは私にとって新しい種類の問題であるため、これにアプローチする方法(または開始方法さえも)がわかりません...どんな助けも大歓迎です!

4

3 に答える 3

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

これが回答を表す場合は、回答としてマークしてください。

于 2012-07-19T02:25:17.453 に答える
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

ここをクリックし、例を含む記事を参照してください。

于 2012-07-19T01:49:02.390 に答える
1

私はこれを2つの方法で解決することになりました。残念ながら非常に遅い私の最初の方法は次のとおりです。

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)
于 2012-07-19T03:18:13.097 に答える