1

我有一张桌子:

租约 ID、套件 ID

租赁是一把钥匙,您可以在一个租赁中拥有多个套房。我正在尝试创建一个查询,向我显示与租约关联的所有套件,本质上是如下输出:

租赁 ID:1 套件列表:A1、A2、B1

不幸的是,我不确定如何解决这个问题(甚至如何开始),因为这对我来说是一种新的问题......任何帮助将不胜感激!

4

3 回答 3

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

我假设你的桌子叫做 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

我最终以两种方式解决了这个问题。我的第一种方法,不幸的是很慢是:

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 回答