根据病情取行(Fetch rows based on condition)

2019-11-04 04:32发布

我使用亚马逊红移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'

我不得不比startendtime交替记录为TimeDifference <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有条件时失败。

Answer 1:

有两个原因, row y没有被返回是由于条件:

  • b.start > a.start意味着行永远不会与自己加盟
  • 本集团将返回每一个记录APP_nm值,但所有行具有相同的值。

然而,也有将无法成功处理查询进一步的逻辑错误。 例如,它如何知道一个“新”会话开始时?

你所寻求的逻辑可以在正常的PostgreSQL用的帮助来实现DISTINCT ON功能,其示出了在一个特定的列每个输入值的一行。 然而, DISTINCT ON不红移支持。

一些可能的解决办法: DISTINCT ON红移一样的功能

你所寻求的输出将使用编程语言(可以遍历结果和存储变量),但很难申请到一个SQL查询(其目的是对结果的行操作)是微不足道的。 我会建议提取数据,并通过一个简单的脚本(在Python如)运行它可能然后输出的开始和结束的组合,你所追求的。

这是一个很好的用例为Hadoop的流媒体功能 ,这是我在过去的成功实施。 这将需要记录作为输入,然后“记住”的开始时间,只会输出时所期望的最终逻辑已经达到创纪录的。



Answer 2:

听起来像你后有什么活动事件的“sessionisation”。 您可以使用实现在红移的Windows功能 。

完整的解决方案可能是这样的:

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(子查询名称):

  1. sessioned -我们首先识别开关行(出去和),其中端部和开始之间的持续时间超出了限定范围的行。
  2. with_row_number -只是一个补丁来提取第一行,因为没有开关进去(还有就是我们记录为“开始”隐式开关)
  3. with_boundary -那么我们查明特定交换机发生行。 如果您在自己独立运行子查询很显然,当会话开始session_switch = 0 AND reverse_session_switch = 1时,相反的发生,并且结束。 所有其他行都是在会议中间,从而被忽略。
  4. with_end -最后,我们结合“开始” /“结束”行到(由此定义会话持续时间)的结束/开始,并取出端的行

with_boundary子查询回答您最初的问题,但通常你会想这些行结合起来,得到最终的结果是会话持续时间。



文章来源: Fetch rows based on condition