2017-04-22 78 views
0

我目前拥有以下表单的一些数据。Postgres/AWS Redshift:将数据透视数据转换为长格式

userid |  event_time  | event_duration (secs) | first_activity | last_activity 
    A  2017-01-01 02:20:34    16    E1     E2  
    A  2017-03-01 11:23:43    12    E2     E6 
    B  2017-01-01 08:24:32    53    E1     E4 
    C  2017-01-01 23:19:21    43    E3     E11 

我想进入它的形式:

userid |  event_time  | activity 
    A  2017-01-01 02:20:34  E1 
    A  2017-01-01 02:20:50  E2  
    A  2017-03-01 11:23:43  E2     
    A  2017-03-01 11:23:55  E6 
    B  2017-01-01 08:24:32  E1     
    B  2017-01-01 08:25:25  E4 
    C  2017-01-01 23:19:21  E3     
    C  2017-01-01 23:20:04  E11 

我可以做到这一点很容易:

SELECT userid, event_time, first_activity 
FROM table 
UNION 
SELECT userid, event_time + event_duration * interval '1 seconds', last_activity 
FROM table 

不过,我想办法,以避免重复查询两次使用UNION s。有两种方法可以创建我需要的表单而不需要两个查询吗?

+0

如果您使用Redshift,请勿使用Postgres标记问题。 [来自Redshift手册](http://docs.aws.amazon.com/redshift/latest/dg/c_unsupported-postgresql-features.html):“*不要认为Amazon Redshift和PostgreSQL具有的元素的语义共同点是相同的*“ –

回答

2

这个问题被标记为Postgres时,这个答案写。

您可以使用横向联接:

select v.* 
from t, lateral 
    (values (t.userid, t.eventtime, t.first_activity), 
      (t.userid, t.eventtime + t.event_duration * interval '1 second', t.last_activity) 
    ) v(userid, eventtime, activity); 

作为编者注。你可以这样写没有逗号:

select v.* 
from t cross join lateral 
    (values (t.userid, t.eventtime, t.first_activity), 
      (t.userid, t.eventtime + t.event_duration * interval '1 second', t.last_activity) 
    ) v(userid, eventtime, activity); 

, lateral是一个情况下我其实更喜欢FROM子句中的逗号。有趣的是,SQL Server使用APPLY关键字进行横向连接。 Oracle支持LATERALAPPLY

+0

Oracle自12.1支持横向:https://www.slideshare.net/MarkusWinand/modern-sql/11 –

+0

@MarkusWinand。 。 。谢谢。 –

+0

@GordonLinoff:不幸的是''横向''在v(userid,eventime,activity)上给出了下面的错误':'函数值(字符变化,时间戳没有时区,字符变化)不存在' – Black

相关问题