计算PostgreSQL中的转发日期

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算PostgreSQL中的转发日期相关的知识,希望对你有一定的参考价值。

有一个PostgreSQL查询运行良好,但似乎不是很有效...

SELECT
    _id,
    location,
    day,
    title,
    teacher,
    canceled,
    CASE
      WHEN day <= EXTRACT(dow from CURRENT_DATE)::integer THEN CURRENT_DATE + day + (6 - EXTRACT(dow from CURRENT_DATE)::integer) + "startTime"  
      WHEN day > EXTRACT(dow from CURRENT_DATE)::integer THEN CURRENT_DATE + (day - EXTRACT(dow from CURRENT_DATE)::integer - 1) + "startTime"
    END AS "startTime",
    CASE
      WHEN day <= EXTRACT(dow from CURRENT_DATE)::integer THEN CURRENT_DATE + day + (6 - EXTRACT(dow from CURRENT_DATE)::integer) + "endTime"  
      WHEN day > EXTRACT(dow from CURRENT_DATE)::integer THEN CURRENT_DATE + (day - EXTRACT(dow from CURRENT_DATE)::integer - 1) + "endTime"
    END AS "endTime"
    FROM "Schedules"
    ORDER BY location, day, "startTime";

在这种情况下,日列是星期几(1-7,而不是0-6)。它显示从当前日期开始的日期,因此如果是星期三(第4天),则显示日期= 4作为当前日期,日= 5是当前日期+ 1等的记录。如果星期几较低,则显示下周的日期。

有人会有任何关于优化这个的建议吗?

答案

加6,减去the day of the week dow并取模7(% is the modulo operator)。 这是要添加的天数(0-6):

SELECT _id, location, day, title, teacher, canceled
      , now()::date + ((day + 6 - EXTRACT(dow from now())::int) % 7) + "startTime"
      , now()::date + ((day + 6 - EXTRACT(dow from now())::int) % 7) + "endTime"
FROM    "Schedules"
ORDER   BY location, day, "startTime";

有关:

或者,为了避免重复表达(但我怀疑它会更快):

SELECT _id, location, day, title, teacher, canceled
     , t.d + "startTime"
     , t.d + "endTime"
FROM   "Schedules" s
, LATERAL (SELECT now()::date + (s.day + 6 - EXTRACT(dow from now())::int) % 7) t(d)
ORDER  BY location, day, "startTime";
另一答案

在不查看数据和索引的情况下很难知道,但是您可以尝试计算DOW一次并使用它而不是提取这么多次,这将使您的查询更有效,更可读。

EG

SELECT your_columns
      ,case when day <= v.curr_dow then 
                 current_day + day + 6 - v.curr_dow + startTime
            else current_day + day - 1 - v.curr_dow + startTime
            end as startTime
      ...
FROM   your_table
      cross join (values(extract(dow from current_date)::integer)) AS v(curr_dow)
另一答案

一个改进是仅计算当前的一周中的一天:

SELECT
    _id,
    location,
    day,
    title,
    teacher,
    canceled,
    CASE
        WHEN day <= current.dow THEN CURRENT_DATE + day + (6 - current.dow) + "startTime"
        WHEN day > current.dow THEN CURRENT_DATE + (day - current.dow - 1) + "startTime"
    END AS "startTime",
    CASE
        WHEN day <= current.dow THEN CURRENT_DATE + day + (6 - current.dow) + "endTime"
        WHEN day > current.dow THEN CURRENT_DATE + (day - current.dow - 1) + "endTime"
    END AS "endTime"
    FROM "Schedules"
        FULL JOIN (
            SELECT EXTRACT(dow from CURRENT_DATE)::integer AS dow
        ) AS current
        ON TRUE
    ORDER BY location, day, "startTime";

以上是关于计算PostgreSQL中的转发日期的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 中的窗口函数尾随日期

如何计算日历表中只有值为 1 的 2 列日期之间的天数 - postgreSQL?

如何计算 Postgresql 中特定日期最后 7 行的累积总和?

PostgreSQL 给定日期间隔初始时间计算

PostgreSQL 当月最后一天的工作日 , 计算日期是星期几

如何用 postgresql 计算排列?