【问题标题】:How to get the end of a day?如何结束一天的工作?
【发布时间】:2015-02-25 16:04:26
【问题描述】:

我正在使用PostgreSQL 8.4。我有一个表my_tbl 的列,其中包含日期(timestamp without timezone)。例如:

       date
-------------------
2014-05-27 12:03:20
2014-10-30 01:20:03
2013-10-19 16:34:34
2013-07-10 15:24:26
2013-06-24 18:15:06
2012-07-14 07:09:14
2012-05-13 04:46:18
2013-01-04 21:31:10
2013-03-26 10:17:02

如何编写返回格式中所有日期的 SQL 查询:

xxxx-xx-xx 23:59:59

也就是说,每个日期都将设置为一天的结束。

【问题讨论】:

    标签: sql postgresql date-arithmetic


    【解决方案1】:

    很多方法。

    在我的示例中使用列名 "ts"timestamp 列的“日期”会产生误导。

    1.

    转换为date。 (这里我们需要 date 类型。在其他表达式中,date_trunc() 也一样。)。然后在减去区间1 second之前加上1(integer):

    SELECT ts::date + 1 - interval '1 sec' AS last_sec_of_day
    

    2.

    添加一个单个间隔'1 day - 1 sec'。不需要两个操作,Postgres interval input 允许单个表达式。

    SELECT ts::date + interval '1 day - 1 sec' AS last_sec_of_day
    

    3.

    更简单,将所需的时间组件添加到日期:

    SELECT ts::date + time '23:59:59' AS last_sec_of_day
    

    4.

    但是,xxxx-xx-xx 23:59:59 不是“一天的结束”。 Postgres timestamp data type(目前,但不太可能更改)以微秒级分辨率存储值。
    一天中可能的最新时间戳是xxxx-xx-xx 23:59:59.999999

    SELECT ts::date + interval '1 day - 1 microsecond' AS last_ts_of_day
    

    5.

    等效:

    SELECT ts::date + time '23:59:59.999999' AS last_ts_of_day  -- or interval
    

    最后一个表达式应该是除了正确之外最快的

    6.

    然而,更好的方法通常是以第二天的开始作为唯一的上限,它不依赖于实现细节,甚至更简单生成:

    SELECT ts::date + 1 AS next_day
    

    7.

    第二天的实际第一个时间戳:

    SELECT date_trunc('day', ts) + interval '1 day' AS next_day_1st_ts
    

    至少从 Postgres 8.4 开始,所有版本都可以工作。 Postgres 13 中的演示:

    db小提琴here

    【讨论】:

      【解决方案2】:

      取日期,截断,加一日减一秒:

      select date_trunc('day', date) + interval '1 day' - interval '1 second'
      

      如果要更改表中的数据,可以将逻辑放在update 中。

      当然也可以加24*60*60-1秒:

      select date_trunc('day', date) + (24*60*60 - 1) * interval '1 second'
      

      但这似乎不太优雅。

      【讨论】:

      • 只是补充一点,如果你想要精确到毫秒,你可以用 'millisecond' 替换 'second' 部分,最后是 'xxxx-xx-xx 23:59:59.999'。跨度>
      • 我喜欢select the_date::date + interval '1 day - 1 second'; 另外,不要用保留字来命名列。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-30
      • 2012-02-27
      • 1970-01-01
      • 2016-07-24
      • 2020-11-04
      • 2021-10-24
      • 1970-01-01
      相关资源
      最近更新 更多