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