在PostgreSQL中计算远期日期

时间:2019-02-27 21:43:51

标签: postgresql datetime

得到了一个运行良好但效率不高的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为当前日期,day = 5为当前日期+ 1,依此类推。如果星期几较低,则显示下周的日期。

有人会对优化这一点有什么建议吗?

3 个答案:

答案 0 :(得分:0)

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

例如

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)

答案 1 :(得分:0)

一项改进是仅一次计算当前星期几:

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";

答案 2 :(得分:0)

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

ifelse()

相关:

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

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";