我在Amazon Redshift上使用PostgreSQL。
我的表是:
drop table APP_Tax;
create temp table APP_Tax(APP_nm varchar(100),start timestamp,end1 timestamp);
insert into APP_Tax values('AFH','2018-01-26 00:39:51','2018-01-26 00:39:55'),
('AFH','2016-01-26 00:39:56','2016-01-26 00:40:01'),
('AFH','2016-01-26 00:40:05','2016-01-26 00:40:11'),
('AFH','2016-01-26 00:40:12','2016-01-26 00:40:15'), --row x
('AFH','2016-01-26 00:40:35','2016-01-26 00:41:34') --row y
预期产出:
'AFH','2016-01-26 00:39:51','2016-01-26 00:40:15'
'AFH','2016-01-26 00:40:35','2016-01-26 00:41:34'
我必须在备用记录之间比较start
和endtime
以及时间差异< 10秒获得下一条记录endtime
,直至最后或最终记录。
I,e datediff(seconds,2018-01-26 00:39:55,2018-01-26 00:39:56) Is <10 seconds
我试过了:
SELECT a.app_nm
,min(a.start)
,max(b.end1)
FROM APP_Tax a
INNER JOIN APP_Tax b
ON a.APP_nm = b.APP_nm
AND b.start > a.start
WHERE datediff(second, a.end1, b.start) < 10
GROUP BY 1
虽然有效,但在条件失败时不会返回row y
。
答案 0 :(得分:0)
有两个原因导致row y
未返回是由于条件:
b.start > a.start
表示一行永远不会自行加入APP_nm
值只返回一条记录,但所有行都具有相同的值。但是,查询中还有一些逻辑错误无法成功处理。例如,它如何知道&#34; new&#34;会议开始了?
您所寻找的逻辑可以在普通的PostgreSQL中借助DISTINCT ON
函数实现,该函数在特定列中显示每个输入值一行。但是,Redshift不支持DISTINCT ON
。
一些可能的解决方法:DISTINCT ON like functionality for Redshift
使用编程语言(可以遍历结果并存储变量),您寻找的输出将是微不足道的,但很难应用于SQL查询(设计用于对结果行进行操作)。我建议提取数据并通过一个简单的脚本(例如在Python中)运行,然后输出Start&amp;你寻求的最终组合。
这是Hadoop Streaming function的一个很好的用例,我过去已经成功实现了它。它将记录作为输入,然后记住&#39;开始时间,只有在满足所需的结束逻辑时才输出记录。
答案 1 :(得分:0)
听起来你所追求的是活动事件的“会话化”。您可以使用Windows Functions在Redshift中实现此目的。
完整的解决方案可能如下所示:
SELECT
start AS session_start,
session_end
FROM (
SELECT
start,
end1,
lead(end1, 1)
OVER (
ORDER BY end1) AS session_end,
session_boundary
FROM (
SELECT
start,
end1,
CASE WHEN session_switch = 0 AND reverse_session_switch = 1
THEN 'start'
ELSE 'end' END AS session_boundary
FROM (
SELECT
start,
end1,
CASE WHEN datediff(seconds, end1, lead(start, 1)
OVER (
ORDER BY end1 ASC)) > 10
THEN 1
ELSE 0 END AS session_switch,
CASE WHEN datediff(seconds, lead(end1, 1)
OVER (
ORDER BY end1 DESC), start) > 10
THEN 1
ELSE 0 END AS reverse_session_switch
FROM app_tax
)
AS sessioned
WHERE session_switch != 0 OR reverse_session_switch != 0
UNION
SELECT
start,
end1,
'start'
FROM (
SELECT
start,
end1,
row_number()
OVER (PARTITION BY APP_nm
ORDER BY end1 ASC) AS row_num
FROM APP_Tax
) AS with_row_number
WHERE row_num = 1
) AS with_boundary
) AS with_end
WHERE session_boundary = 'start'
ORDER BY start ASC
;
这是breadkdown(通过子查询名称):
sessioned
- 我们首先确定切换行(out和in),其中end和start之间的持续时间超出限制的行。 with_row_number
- 只是一个提取第一行的补丁,因为没有切换到它(有一个我们记录为'start'的隐式开关)with_boundary
- 然后我们确定特定开关发生的行。如果您自己运行子查询,则很明显会话在session_switch = 0 AND reverse_session_switch = 1
时开始,并在相反的情况下结束。所有其他行都在会话中间,因此会被忽略。with_end
- 最后,我们将'start'/'end'行的结束/开始合并(从而定义会话持续时间),并删除结束行 with_boundary
子查询回答了您的初始问题,但通常您希望将这些行组合起来以获得最终结果,即会话持续时间。