如何在一行中合并多行

时间:2016-04-21 20:23:27

标签: sql sql-server sql-server-2008 join

我有以下临时表,用于列出酒店的当前房间状态

    declare @CurrentDate datetime = '2016-04-21' 
    select Lodging, Room, FirstName, LastName, TempStatus, @CurrentDate as CurrentDate
    from RoomAvailability

这是以下结果:

    Lodging     Room    FirstName   LastName    TempStatus  CurrentDate
    -------------------------------------------------------------------------------
    marriok     119     Super       Man     Next guest      2016-03-24 00:00:00.000
    marriok     101     Bat         Man     Next guest      2016-03-24 00:00:00.000
    marriok     123     Aqua        Man     Leaving today   2016-03-24 00:00:00.000
    marriok     103     Wonder      Woman   Leaving today   2016-03-24 00:00:00.000
    marriok     101     Lex         Luthor  Leaving today   2016-03-24 00:00:00.000

这是我的预期结果:

    Lodging     Room    CurrFirstName       CurrLastName    TempStatus      CurrentDate                 NextFistName    NextLastName    TempStatus
    ----------------------------------------------------------------------------------------------------------------------------------------------
    marriok     119     Super               Man             Next guest      2016-03-24 00:00:00.000     NULL            NULL            NULL
    marriok     123     Aqua                Man             Leaving today   2016-03-24 00:00:00.000     NULL            NULL            NULL
    marriok     103     Wonder              Woman           Leaving today   2016-03-24 00:00:00.000     NULL            NULL            NULL
    marriok     101     Lex                 Luthor          Leaving today   2016-03-24 00:00:00.000     Bat             Man             Next guest

我试过了:

    declare @CurrentDate datetime = '2016-04-21' 
    select coalesce(a.Lodging, b.Lodging) as Lodging, 
        coalesce(a.Room, b.Room) as Room, 
        a.FirstName as CurrFirstName, a.LastName as CurrLastName, a.TempStatus, @CurrentDate,
        b.NextFirstName, b.NextLastName, b.TempStatus
    from RoomAvailability a
    full join RoomAvailability b
        on a.Lodging = b.Lodging
        and a.Room = b.Room

我得到了这个:

    Lodging     Room    CurrFirstName       CurrLastName    TempStatus      CurrentDate                 NextFistName    NextLastName    TempStatus
    ----------------------------------------------------------------------------------------------------------------------------------------------
    marriok     119     Super               Man             Next guest      2016-03-24 00:00:00.000     Super           Man             Next guest
    marriok     101     Bat                 Man             Next guest      2016-03-24 00:00:00.000     Bat             Man             Next guest
    marriok     101     Bat                 Man             Next guest      2016-03-24 00:00:00.000     Lex             Luthor          Leaving today
    marriok     123     Aqua                Man             Leaving today   2016-03-24 00:00:00.000     Aqua            Man             Leaving today
    marriok     103     Wonder              Woman           Leaving today   2016-03-24 00:00:00.000     Wonder          Woman           Leaving today
    marriok     101     Lex                 Luthor          Leaving today   2016-03-24 00:00:00.000     Bat             Man             Next guest
    marriok     101     Lex                 Luthor          Leaving today   2016-03-24 00:00:00.000     Lex             Luthor          Leaving today

那么我怎样才能获得独特或合并的行并列出在同一天离开并到达同一房间的人? (没有CTE优先)

更新

临时表RoomAvailability是带有union all

的3个select语句的乘积

3个select语句是相同的,它们只是在where子句中有所不同。在这3个select语句中包含一个签入和签出日期时间列。

我的第一个选择按照登记和退房日期(不包括)之间的当前日期变量进行过滤。我添加了一个列为“内部”的列。

我的第二个选择按当前日期变量等于办理登机手续进行过滤,我添加了状态文字“下一位客人”

最后一个选择按当前日期变量等于结账,我添加了状态'今天离开'。

更新2

如果没有CTE,这离我更近了

select coalesce(a.Lodging, b.Lodging), 
    coalesce(a.Room, b.Room), 
    a.FirstName, a.LastName, a.TempStatus, 
    b.FirstName, b.LastName, b.TempStatus,
    @CurrentDate
from RoomAvailability a
left join RoomAvailability b
    on a.Lodging = b.Lodging
    and a.Room = b.Room
    and a.TempStatus != b.TempStatus

但它在最后重复同一个房间的行

marriok 119 Super   Man     Next guest      NULL    NULL    NULL            2016-04-21
marriok 101 Bat     Man     Next guest      Lex     Luthor  Leaving today   2016-04-21
marriok 123 Aqua    Man     Leaving today   NULL    NULL    NULL            2016-04-21
marriok 103 Wonder  Woman   Leaving today   NULL    NULL    NULL            2016-04-21
marriok 101 Lex     Luthor  Leaving today   Bat     Max     Next guest      2016-04-21 --<-- this should not be displayed

1 个答案:

答案 0 :(得分:1)

如果您使用的是SQL 2012及更高版本,则最终查询会更简单。

假设您的数据位于名为#t

的表中

设置数据

create table #t (
    Lodging varchar(10)
    , Room int
    , FirstName  varchar(10)
    , LastName  varchar(10)
    , TempStatus  varchar(20)
    , CurrentDate datetime
)

insert into #t values
('marriok'     ,119     ,'Super'       ,'Man'     ,'Next guest'      ,'2016-03-24'),
('marriok'     ,101     ,'Bat'         ,'Man'     ,'Next guest'      ,'2016-03-24'),
('marriok'     ,123     ,'Aqua'        ,'Man'     ,'Leaving today'   ,'2016-03-24'),
('marriok'     ,103     ,'Wonder'      ,'Woman'   ,'Leaving today'   ,'2016-03-24'),
('marriok'     ,101     ,'Lex'         ,'Luthor'  ,'Leaving today'   ,'2016-03-24')

您的查询将是

with sortIt as (
    select *, case TempStatus 
                  when 'Next guest' then 2 
                  when 'Leaving today' then 1 
              end as Sort 
    from #t
)
, addFld as (
    select t1.*, t2.FirstName as NextFirstName, t2.LastName as NextLastName
        , t2.TempStatus as NextTempStatus 
    from sortIt t1
        left join sortIt t2 on t2.Room = t1.Room and t2.Sort = t1.Sort + 1
)
, removDup as ( 
    select *, ROW_NUMBER() over (partition by Room order by NextFirstName desc) rn
    from addFld
)
select * from removDup
where rn = 1

结果

+---------+------+-----------+----------+---------------+-------------------------+------+---------------+--------------+----------------+----+
| Lodging | Room | FirstName | LastName |  TempStatus   |       CurrentDate       | Sort | NextFirstName | NextLastName | NextTempStatus | rn |
+---------+------+-----------+----------+---------------+-------------------------+------+---------------+--------------+----------------+----+
| marriok |  101 | Lex       | Luthor   | Leaving today | 2016-03-24 00:00:00.000 |    1 | Bat           | Man          | Next guest     |  1 |
| marriok |  103 | Wonder    | Woman    | Leaving today | 2016-03-24 00:00:00.000 |    1 | NULL          | NULL         | NULL           |  1 |
| marriok |  119 | Super     | Man      | Next guest    | 2016-03-24 00:00:00.000 |    2 | NULL          | NULL         | NULL           |  1 |
| marriok |  123 | Aqua      | Man      | Leaving today | 2016-03-24 00:00:00.000 |    1 | NULL          | NULL         | NULL           |  1 |
+---------+------+-----------+----------+---------------+-------------------------+------+---------------+--------------+----------------+----+