代码之家  ›  专栏  ›  技术社区  ›  Gothmog

将行转换为允许重复的列

  •  1
  • Gothmog  · 技术社区  · 16 年前

    考虑下表和行:

    清单A。

    ID, name, event, type
    1, 'John Doe', '2010-09-01 15:00:00.000', 'input'
    1, 'John Doe', '2010-09-03 11:00:00.000', 'input'
    1, 'John Doe', '2010-09-04 17:00:00.000', 'input'
    1, 'John Doe', '2010-09-02 15:00:00.000', 'output'
    1, 'John Doe', '2010-09-03 16:00:00.000', 'output'
    1, 'John Doe', '2010-09-06 17:00:00.000', 'output'
    

    我想要的是将行转换为列,这样就可以有两个不同的列,input event和output event。比如:

    清单B。

    ID, name, input event, output event
    1, 'John Doe', '2010-09-01 15:00:00.000', '2010-09-02 15:00:00.000'
    1, 'John Doe', '2010-09-03 11:00:00.000', '2010-09-03 16:00:00.000'
    1, 'John Doe', '2010-09-04 17:00:00.000', '2010-09-06 17:00:00.000'
    

    我得到了如下结果:

    清单C。

    ID, name, input event, output event
    1, 'John Doe', '2010-09-01 15:00:00.000', null
    1, 'John Doe', '2010-09-03 11:00:00.000', null
    1, 'John Doe', '2010-09-04 17:00:00.000', null
    1, 'John Doe', null, '2010-09-02 15:00:00.000'
    1, 'John Doe', null, '2010-09-03 16:00:00.000'
    1, 'John Doe', null, '2010-09-06 17:00:00.000'
    

    ,但问题是如何平铺行,因为重复的元组ID名称是相关的。要将行转换为列,我通常编写如下代码:

    select ID, name, max(case when type = 'input' then event else null end) as 'input event', max(case when type = 'output' then event else null end) as 'output event' from events group by ID, name
    

    当然,组员会去掉重复的,这是我不想要的。

    有没有办法通过查询来实现这一点?

    如果有一个可移植的sql解决方案或postgresql,那就太好了,但是任何想法都是非常感谢的。

    3 回复  |  直到 16 年前
        1
  •  2
  •   user359040 user359040    16 年前

    select ID, name, event as 'input event', 
           (select min(o.event) 
            from events o 
            where o.type = 'output' and 
                  i.ID = o.ID and 
                  i.name = o.name and 
                  i.event < o.event) as 'output event' 
    from events i
    where i.type = 'input'
    group by ID, name, event
    
        2
  •  1
  •   bluish dmajkic    15 年前
    select t1.id,t1.name,t1.event,t2.event from test t1
        inner join test t2 on t1.event <= t2.event 
            and t1.type = 'input' 
            and t2.type = 'output'
                       and t1.id = t2.id
                       and t1.name = t2.name
    

    问题是您需要以某种方式链接输入/输出会话。在这个查询中,我使用timestamp事件列来完成它。如果这不是你想要的,你能提供更多的信息吗?

    更新: 现在,你可以做一些后期处理

    with a as
    (
    select t1.id,t1.name,t1.event as in_event,t2.event as out_event from test t1
        inner join test t2 on t1.event <= t2.event 
                       and t1.type = 'input' 
                       and t2.type = 'output'
                       and t1.id = t2.id
                       and t1.name = t2.name
    )
    select id,name,in_event,min(out_event)
           from a
    group by id,name,in_event
    
        3
  •  0
  •   Burcin    16 年前

    create table #a(
    ID int,
    name varchar(30),
    event datetime,
    type varchar(10)
    )
    
    insert #a
    select  
    1, 'John Doe', '2010-09-01 15:00:00.000', 'input'
    union select 1, 'John Doe', '2010-09-01 16:00:00.000', 'input'
    union select 1, 'John Doe', '2010-09-01 17:00:00.000', 'input'
    union select 1, 'John Doe', '2010-09-02 15:00:00.000', 'output'
    union select 1, 'John Doe', '2010-09-02 16:00:00.000', 'output'
    union select 1, 'John Doe', '2010-09-02 17:00:00.000', 'output'
    

    select 
        ID, 
        name, 
        case when type = 'input' then event else null end "input event",
        case when type = 'output' then event else null end "output event"
     from #a