【问题标题】:How to Find Consecutive Dates in Postgres SQL如何在 Postgresql 中查找连续的日期
【发布时间】:2021-08-07 20:25:25
【问题描述】:

我在postgres数据库中有如下表(表名为table_test):

          id             dia          Data_sensor_Analog
         2165         2020-09-20       4585542
         2165         2020-09-21       4954566
         2165         2020-09-26           255 

我想计算属性dia的连续天数。

为此,我尝试编写以下代码:

           WITH 

           groups AS (
           SELECT
              ROW_NUMBER() OVER (ORDER BY dia) AS rn,
              dateadd(dia, -ROW_NUMBER() OVER (ORDER BY dia), dia) AS grp,
              dia
           FROM table_test
          )

          SELECT
          COUNT(*) AS consecutiveDates,
          MIN(dia) AS minDate,
          MAX(dia) AS maxDate
          FROM groups
          GROUP BY grp
          ORDER BY 1 DESC, 2 DESC

我希望输出是:

             consecutiveDates       minDate        maxDate  
                     1            2020-09-20      2020-09-21

但是,当我运行代码时,出现以下错误消息:

          ERROR:  function dateadd(text, bigint, text) does not exist
          LINE 17:       dateadd(dia, -ROW_NUMBER() OVER (ORDER BY dia), dia) A

我正在使用 postgres,并在网站上找到了这个示例代码:https://blog.jooq.org/2015/11/07/how-to-find-the-longest-consecutive-series-of-events-in-sql/

我将dia 属性转换为:

         ALTER TABLE table_test
         ALTER COLUMN dia
         TYPE TIMESTAMP WITHOUT TIME ZONE
         USING dia::timestamp without time zone;

【问题讨论】:

  • Postgresql 函数被输入。如果调用中的某些参数类型错误,您将收到此错误。查找函数定义并进行比较,然后转换参数以满足函数签名。主要是它可能需要日期时间而不是文本作为输入。

标签: sql postgresql window-functions


【解决方案1】:

考虑到您的表中一天只有一个条目,请尝试以下操作:

select id, count(*) -1 "count", max(dia), min(dia) from (
select *, 
date(dia) - row_number() over (partition by id order by date(dia)) * interval '1 day' "filter" 
from table_test
) t1 
group by id, filter
having count(*) -1 > 0

DEMO

如果同一日期有多个值,请尝试以下操作:

with cte as (
select 
*,
date(dia) date_,date(dia) - dense_rank() over ( partition by id order by date(dia)) * interval '1 day' "filter" 
from table_test
)
select 
id, count(distinct date_) -1 "count" , max(dia),min(dia) 
from cte
group by id, filter
having count(distinct date_) -1 >0

DEMO

【讨论】:

  • 完美运行!在与“table_test”表结构相同的原始表中,我还有其他标识符(id)。问题是如何按 id 计算连续天数?
  • 它是对 dense_rank() 或 row_number() 的微小变化。根据您的要求更新答案
  • 完美运行!
【解决方案2】:

你可以减去一个枚举值,但你需要一个子查询或 CTE:

select min(dia), max(dia), count(*)
from (select t.*,
             row_number() over (order by dia) as seqnum
      from table_test t
     ) t
group by dia - seqnum * interval '1 day';

但是,看起来dia 是一个字符串而不是日期。为了解决这个问题:

group by (dia::date) - seqnum * interval '1 day';

格式适合转换为日期。

Here 是一个 dbfiddle。

【讨论】:

  • 我在问题中的“dia”属性中添加了类型转换。您的代码已执行。但是,答案不仅仅显示所需的输出。它显示“直径”2020-09-26 为最大值和最小值,计数 = 1。你知道我该如何解决吗?
  • @JaneBorges 。 . .当然。如果您只想要包含多个日期的行,请添加 having count(*) > 1。您的问题并不清楚您想要什么结果。
猜你喜欢
  • 1970-01-01
  • 2021-03-23
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多