【问题标题】:SQL: find if there are 10 consecutive dates that have a certain value in another column in redshiftSQL:在redshift的另一列中查找是否有10个连续日期具有特定值
【发布时间】:2021-03-12 21:14:37
【问题描述】:

redshift SQL 中有没有办法判断 Rates='Y' 的连续 10 天是否存在?在下面的示例中,答案是否定的。

表格名称:费率

Dates        Rates
1/1/2021       Y
1/2/2021       Y
1/3/2021       Y
1/4/2021       N
1/5/2021       N
1/6/2021       N
1/7/2021       Y
1/8/2021       Y
1/9/2021       Y
1/10/2021      Y
1/11/2021      Y
1/12/2021      Y
1/13/2021      Y

【问题讨论】:

  • 您可以使用一系列 9 个 JOIN (FROM tab t1 JOIN tab t2 on t2.dates = t1.dates - 1) JOIN tab t3 ON t3.dates = t2.dates - 1 JOIN tab t4 ON )。或者您可以使用一系列九个子选择。
  • 我是 sql 新手。你能详细说明一下吗?我不认为我明白。
  • 将其设为 3,然后查看 meta.stackoverflow.com/questions/333952/…

标签: sql logic amazon-redshift


【解决方案1】:

一种方法使用sum() 作为窗口函数和一些聚合。假设您每天有一行(即您想要 10 个)。您可以使用以下方法获取所有连续 10 行的行:

select t.*
from (select t.*, lag(date, 9) over (partition by rates order by date) as prev_date_9
      from t
     ) t
where prev_date_9 = date - interval '9 day' and
      rates = 'Y';

获得标志的一种方法是使用聚合:

select (case when count(*) = 0 then 'No' else 'Yes' end)
from (select t.*, lag(date, 9) over (partition by rates order by date) as prev_date_9
      from t
     ) t
where prev_date_9 = date - interval '9 day' and
      rates = 'Y';

这假设您的数据每天恰好有一行,这就是您问题中数据的结构。

【讨论】:

  • 有趣。您在这里实施什么 RDBMS?我以前从未见过这种“间隔'9天'”;想回顾一下这个很酷的技巧。如果它做到了我认为可能的效果,那么您如何确保 10 天范围内没有缺口?
  • @丹尼斯。 . . interval 是标准 SQL 的一部分。 Postgres 要求整个区间是一个字符串。
  • 刚刚更新了我的评论@Gordon。所以这里没有什么可以确保 10 天期间没有间隔,对吧?
  • 标准的好处:有很多可供选择。 :) 间隔在 IBM DB2 中不存在,在 Oracle 中也不存在。他们有他们的方式,但他们看起来与此不同。
  • @丹尼斯。 . Oracle 确实支持interval (docs.oracle.com/cd/B28359_01/server.111/b28286/…)。但我把 SQL 比作英语。 . .一些区域版本相互无法理解;)
【解决方案2】:

这是一种方法,使用我上面提到的 JOIN 概念:

SELECT t1.dates AS to_date, ta.dates AS from_date
FROM   my_table t1
JOIN   my_table t2 on t2.dates = (t1.dates - 1) AND t2.rates = t1.rates
JOIN   my_table t3 on t3.dates = (t2.dates - 1) AND t3.rates = t1.rates
JOIN   my_table t4 on t4.dates = (t3.dates - 1) and t4.rates = t1.rates
JOIN   my_table t5 on t5.dates = (t4.dates - 1) AND t5.rates = t1.rates
JOIN   my_table t6 on t6.dates = (t5.dates - 1) AND t6.rates = t1.rates
JOIN   my_table t7 on t7.dates = (t6.dates - 1) AND t7.rates = t1.rates
JOIN   my_table t8 on t8.dates = (t7.dates - 1) AND t8.rates = t1.rates
JOIN   my_table t9 on t9.dates = (t8.dates - 1) AND t9.rates = t1.rates
JOIN   my_table ta on ta.dates = (t9.dates - 1) AND ta.rates = t1.rates
WHERE  t1.rates = 'Y'

另一种方法可能更符合您的喜好(JOIN 会使某些人感到困惑):

SELECT t1.dates as to_date, t1-dates - 9 AS from_date
FROM   my_table t1
WHERE  t1.rates = 'Y'
AND EXISTS (SELECT 1 FROM my_table t2 WHERE t2.dates = t1.dates - 1 AND t2.rates = t1.rates)
AND EXISTS (select 1 FROM ... (yes, you would have to type in all the rest...  I'm lazy.)

我知道除了手工编码之外没有其他方法可以确保没有间隙,正如您在此处看到的那样。

还请注意,您没有指定您的 RDBMS,因此我为您提供了一个 DB2-ish 解决方案。您可能需要调整 RDBMS 的 (dates - 1) 语法。

玩得开心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多