Sql 如何连续两天或两天以上/月/季度返回符合条件的行?

Sql 如何连续两天或两天以上/月/季度返回符合条件的行?,sql,postgresql,Sql,Postgresql,我试图返回连续两个月或更长时间内满足>=10 FactCount阈值的行 下面是我当前的输出示例,以及下面的查询 我将如何实现这一点?如果有什么我可以澄清的,请留下评论。谢谢你的意见 现有表格 期望输出 查询: 使用lead获取按yearmonth排序的每个用户ID下一行的factcount。获取当前行的值>=10和下一行的值>=10的所有用户ID。然后从表中选择该用户标识的所有行 select * from tbl where userid in (select userid

我试图返回连续两个月或更长时间内满足>=10 FactCount阈值的行

下面是我当前的输出示例,以及下面的查询

我将如何实现这一点?如果有什么我可以澄清的,请留下评论。谢谢你的意见

现有表格

期望输出

查询:

使用lead获取按yearmonth排序的每个用户ID下一行的factcount。获取当前行的值>=10和下一行的值>=10的所有用户ID。然后从表中选择该用户标识的所有行

select * from tbl 
where userid in (select userid
                 from (select userid, yearmonth, factcount
                      ,lead(factcount) over(partition by userid order by yearmonth) nxt_factcount
                       from tbl) x
                 where factcount >=10 and nxt_factcount >= 10
                ) 
<>编辑:在下一个月考虑下一行,即使缺少FACTCOUNT值,您首先需要生成所有的日期和用户ID组合。使用Generate_series生成所有必需的日期,并将其与用户ID交叉连接。然后将原始表左键连接到此表,并至少检查一次连续factcount>=10的用户

with all_dates as (
SELECT dt:: date
FROM generate_series
        (date '2016-01-01' --change this series start accordingly 
        ,date '2017-12-31' --change this series end accordingly
        ,'1 month') dt
)
,all_months_count_combs as (
select  
 u.userid
,extract(year from a.dt)||'-'||extract(month from a.dt) yearmonth 
,f.factcount
,lead(f.factcount) over(partition by u.userid order by extract(year from a.dt),extract(month from a.dt)) nxt_factcount
from all_dates a
cross join (select distinct userid from foo) u
left join foo f on u.userid=f.userid
and substring(f.yearmonth,1,4)::int=extract(year from a.dt) 
and substring(f.yearmonth,5)::int=extract(month from a.dt) 
)
select * from foo 
where userid in (select distinct userid 
                 from all_months_count_combs 
                 where factcount >=10 and nxt_factcount >=10
                )

我想这就是你想要的

WITH t AS (
  SELECT userid,
    make_date(
      substring(yearmonth::text, 1, 4)::int,
      substring(yearmonth::text, 5, 2)::int,
      1
    ) AS yearmonth,
    factcount
  FROM foo
)
SELECT userid, dategroup, count(*)
FROM (
  SELECT
    userid,
    yearmonth,
    factcount,
    count(is_reset) OVER (PARTITION BY userid ORDER BY yearmonth) AS dategroup
  FROM (
    SELECT
      userid,
      yearmonth,
      factcount,
      CASE WHEN (lag(yearmonth) OVER (PARTITION BY userid ORDER BY yearmonth) + '1 month'::interval)::date <> yearmonth THEN 1 END AS is_reset
    FROM t
    WHERE factcount >= 10
  ) AS t2
) AS t3
GROUP BY userid, dategroup
HAVING count(*) > 1;
我把这个放在CTE里是因为

您不应该像文本YYYYMM那样存储日期 这是一个类型修改,我在开始繁重的工作之前做的,以解决这个孤岛和缺口问题。 接下来我们从里到外工作

SELECT
  userid,
  yearmonth,
  factcount,
  CASE WHEN (lag(yearmonth) OVER (PARTITION BY userid ORDER BY yearmonth) + '1 month'::interval)::date <> yearmonth THEN 1 END AS is_reset
FROM t
WHERE factcount >= 10
然后我们再把它包装一次,然后重新计数

count(is_reset) OVER (PARTITION BY userid ORDER BY yearmonth) AS dategroup
这将返回一个这样的集合

 userid | yearmonth  | factcount | is_reset 
--------+------------+-----------+----------
   5454 | 2016-03-01 |        11 |         
   5454 | 2016-04-01 |        10 |         
   9987 | 2016-03-01 |        12 |         
   9987 | 2016-05-01 |        19 |        1
 userid | yearmonth  | factcount | dategroup 
--------+------------+-----------+-----------
   5454 | 2016-03-01 |        11 |         0
   5454 | 2016-04-01 |        10 |         0
   9987 | 2016-03-01 |        12 |         0
   9987 | 2016-05-01 |        19 |         1
现在我们

按用户ID和日期组分组 选择计数*。 这将显示factcount>10的连续月份的所有用户,而不考虑年份边界

 userid | dategroup | count 
--------+-----------+-------
   5454 |         0 |     2
而且,作为一个额外的奖励,因为它必须做的工作无论如何,它会告诉你

他们连续几个月的factcount>10 如果他们有其他两组连续两个月以上且factcount>10。也就是说,如果1-2-3月和10-12月的factcounts为11呢? 所以你可能会看到

 userid | dategroup | count 
--------+-----------+-------
   5454 |         0 |     3
   5454 |         1 |     2

但是,我认为出于您的目的,您可以使用该输出来做任何您想做的事情。也就是说,如果所有用户的所有行都有两个或更多连续月份且factcount>10,请选择DISTINCT userid,然后连接到主表。

不要这样格式化。使用CREATETABLE作为SELECT向我们显示输入,然后向我们显示所需的输出。您能否澄清-您是否正在寻找实际的SQL CREATETABLE语法?您是否可以创建示例数据的实际表?因为本例中的“input”是我展示的示例表,而所需的输出是“returninquery”列。我将把它改成一个单独的表。我的意思是你的输入表中有交换,FactCount>=10,我们不需要它。如果这就是你想让我们使用的,而FactCount是不相关的,那么不要以任何一种方式显示FactCount,我们不需要两者。此外,此解决方案不会跨越年度界限。请参阅CTA。这正是在讨论复杂查询时所需要的。实际上,这根本不能满足您的需要。它假定leadyearmonth是下一个连续的月份,但可能不是。问题一字排开。我的意思是,如果有两个FactCount>10的1月数据,而3月的2月数据则为零,那么您不希望它显示出来。在这个答案中,它将显示。这个答案也没有考虑年-月滚动。201612和201704将显示它们之间是否存在任何差异。
count(is_reset) OVER (PARTITION BY userid ORDER BY yearmonth) AS dategroup
 userid | yearmonth  | factcount | dategroup 
--------+------------+-----------+-----------
   5454 | 2016-03-01 |        11 |         0
   5454 | 2016-04-01 |        10 |         0
   9987 | 2016-03-01 |        12 |         0
   9987 | 2016-05-01 |        19 |         1
 userid | dategroup | count 
--------+-----------+-------
   5454 |         0 |     2
 userid | dategroup | count 
--------+-----------+-------
   5454 |         0 |     3
   5454 |         1 |     2