Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL-如何在特定行之前选择x行数_Sql_Datetime_Amazon Redshift_Window Functions_Gaps And Islands - Fatal编程技术网

SQL-如何在特定行之前选择x行数

SQL-如何在特定行之前选择x行数,sql,datetime,amazon-redshift,window-functions,gaps-and-islands,Sql,Datetime,Amazon Redshift,Window Functions,Gaps And Islands,我有这张桌子: ts | user_id | event | ------------------------------- 1500 a eat 1501 a walk 1502 a sleep 1500 b eat 1501 b sleep 1502 b wake 1

我有这张桌子:

   ts  |  user_id  |   event   |  
-------------------------------
 1500        a         eat 
 1501        a         walk 
 1502        a         sleep 
 1500        b         eat 
 1501        b         sleep 
 1502        b         wake
 1500        c         walk 
 1501        c         eat
 1502        c         sit
 1503        c         sleep 
 1504        c         wake 
因此,我想在某个事件之前选择
x
行数,假设我想在每个用户id
sleep
之前选择2个事件

我的最终表格结果应该如下所示:

user_id  |   event   |   rank  |
--------------------------------
    a         eat         1
    a         walk        2
    a         sleep       3
    b         NULL        0
    b         eat         1
    b         sleep       2
    c         eat         2
    c         sit         3
    c         sleep       4

如何在SQL(特别是红移SQL)中执行此操作这是一个间隙和孤岛问题,您需要每个孤岛的第一行和最后两行

最安全的方法可能是对睡眠事件进行窗口汇总以定义组,然后使用
行数()进行过滤。


嗯。您可以使用
lead()

注意:这只返回数据中的行。如果需要生成行,则需要附加逻辑

编辑:

实际上,您可以概括如下:

select t.*
from (select t.*,
             sum(case when event = 'sleep') over (partition by user_id order by ts rows between current row and 2 following) as cnt_sleep
      from t
     ) t
where cnt_sleep > 0;

这将统计下一行
n
中的“睡眠”数(n-1)。如果在其中任何一个数据库中发现“sleep”,它将返回一行。

请用您正在运行的数据库标记您的问题:mysql、oraclce、sql server…?如前所述,这是红移sql,我将标记它。谢谢。(1) 如果同一用户睡两次呢?(2) 您需要一个列来对每个用户的行进行排序,您有这样的列吗?SQL表表示无序集。除非列指定了顺序,否则之前没有行。1。如果用户睡眠两次,它仍然必须在每个睡眠事件之前显示x个事件数。2.我正在使用
rank()over(按用户id顺序按日期划分)
为每个用户对行进行排序。很抱歉,我错过了对事件进行排序的列,我确实有时间戳列来对事件进行排序。尝试运行
时,选择t.*,求和(当事件='sleep'时,则为1,否则为0结束)over(按用户id顺序划分)grp从mytable t
,我得到了一个错误
聚合窗口函数,它带有ORDER BY子句,需要一个frame子句
@上瘾:啊,是的,这是一个奇怪的红移限制。我编辑了我的答案。谢谢你。我正在尝试你的提问,并试图获得直觉。嗨@GMB谢谢你的回答。我选择Gordon的答案作为答案,因为它更简单,并且达到了我想要的。如果我需要有3个以前的事件,而不在查询中添加额外的列,该怎么办?仍然理解直觉,但这看起来足够简单,可以得到我想要的。谢谢@Gordon的答案。我选择这个作为最接近我想要的答案。另外,如果我想要固定数量的事件列(如event1、event2、event3),我想我可以使用
lead
函数?@addicted。对Lead允许您将相邻行中的数据放入列中。 ts | user_id | event | grp | rn_asc | rn_desc ---: | :------ | :---- | --: | -----: | ------: 1500 | a | eat | 1 | 1 | 3 1501 | a | walk | 1 | 2 | 2 1502 | a | sleep | 1 | 3 | 1 1500 | b | eat | 1 | 1 | 2 1501 | b | sleep | 1 | 2 | 1 1500 | c | walk | 1 | 1 | 4 1502 | c | sit | 1 | 3 | 2 1503 | c | sleep | 1 | 4 | 1
select *
from (
    select t.*, 
        row_number() over(
            partition by user_id, grp 
            order by ts rows between unbounded preceding and current row
        ) rn_asc,
        row_number() over(
            partition by user_id, grp 
            order by ts rows between unbounded preceding and current row
        ) rn_desc
    from (
        select t.*,
            sum(case when event = 'sleep' then 1 else 0 end) over(
                partition by user_id 
                order by ts desc
                order by ts rows between unbounded preceding and current row
            )  grp
        from mytable t
    ) t
) t
where (rn_asc = 1 or rn_desc <= 2) and grp > 0
order by user_id, ts
select t.*
from (select t.*,
             lead(event) over (partition by user_id order by ts) as next_event,
             lead(event, 2) over (partition by user_id order by ts) as next_event2
      from t
     ) t
where 'sleep' in (event, next_event, next_event2);
select t.*
from (select t.*,
             sum(case when event = 'sleep') over (partition by user_id order by ts rows between current row and 2 following) as cnt_sleep
      from t
     ) t
where cnt_sleep > 0;