如何比较Postgresql中datetime字段中的日期?

use*_*264 148 sql database postgresql date

在postgresql(Windows版本9.2.4)中比较日期时,我遇到了一个奇怪的情况.我的表中有一列说update_date,类型为'timestamp without timezone'.客户可以仅使用日期(即:2013-05-03)或日期与时间(即:2013-05-03 12:20:00)搜索此字段.此列的值为当前所有行的时间戳,并且具有相同的日期部分(2013-05-03)但时间部分不同.

当我在这个专栏中进行比较时,我得到了不同的结果.如下:

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date < '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-04' -> results found

select * from table where update_date >= '2013-05-03' -> results found
Run Code Online (Sandbox Code Playgroud)

我的问题是如何才能使第一个查询获得结果,我的意思是为什么第三个查询工作但不是第一个?

任何人都可以帮我吗?提前致谢.

jus*_*ody 233

@Nicolai关于转换是正确的,以及为什么任何数据的条件都是假的.我想你更喜欢第一种形式,因为你想避免输入字符串上的日期操作,对吗?你不需要害怕:

SELECT *
FROM table
WHERE update_date >= '2013-05-03'::date
AND update_date < ('2013-05-03'::date + '1 day'::interval);
Run Code Online (Sandbox Code Playgroud)

  • @FrozenFlame是的.标准语法是`CAST('2013-05-03'AS DATE)+ CAST('1天'AS INTERVAL)`(IIRC).YMMV关于"DATE"和"INTERVAL"的存在和行为. (5认同)
  • 难道 `WHERE update_date::date = '2013-05-03' ` 也能工作并且可能更具可读性吗? (2认同)

Nic*_*lai 39

update_date >= '2013-05-03'postgres强制转换值与同一类型进行比较以比较值时.因此,您的'2013-05-03'已投放到'2013-05-03 00:00:00'.

所以对于update_date ='2013-05-03 14:45:00'你的表达式将是:

'2013-05-03 14:45:00' >= '2013-05-03 00:00:00' AND '2013-05-03 14:45:00' <= '2013-05-03 00:00:00'
Run Code Online (Sandbox Code Playgroud)

这总是如此 false

要解决此问题,请将update_date强制转换为date:

select * from table where update_date::date >= '2013-05-03' AND update_date::date <= '2013-05-03' -> Will return result
Run Code Online (Sandbox Code Playgroud)

  • 与转换查询参数的单个值相比,转换表中的每个“update_date”效率非常低,并且会确保服务器无法利用该列上的索引。我很想-1这个。 (3认同)
  • 是的,我同意每个值的转换是低效的,你可以给这个解决方案-1.但我描述了问题的原因,并举例说明了这个问题.现在user2866264知道为什么他的查询没有返回预期的行,并将决定什么样的解决方案更适合他的独特案例. (3认同)

小智 9

使用日期转换与日期进行比较:试试这个:

select * from table 
where TO_DATE(to_char(timespanColumn,'YYYY-MM-DD'),'YYYY-MM-DD') = to_timestamp('2018-03-26', 'YYYY-MM-DD')
Run Code Online (Sandbox Code Playgroud)


Clo*_*eto 6

使用range类型.如果用户输入日期:

select *
from table
where
    update_date
    <@
    tsrange('2013-05-03', '2013-05-03'::date + 1, '[)');
Run Code Online (Sandbox Code Playgroud)

如果用户输入时间戳,那么您不需要该::date + 1部件

http://www.postgresql.org/docs/9.2/static/rangetypes.html

http://www.postgresql.org/docs/9.2/static/functions-range.html


iva*_*ncz 6

您还可以使用BETWEEN运算符。

这是一个简单的例子:

SELECT
    customer_id,
    payment_id,
    amount,
    payment_date
FROM
    payment
WHERE
    payment_date BETWEEN '2007-02-07' AND '2007-02-15';
Run Code Online (Sandbox Code Playgroud)

您还可以选择不在这些日期之间的所有内容:

SELECT
    customer_id,
    payment_id,
    amount,
    payment_date
FROM
    payment
WHERE
    payment_date NOT BETWEEN '2007-02-07' AND '2007-02-15';
Run Code Online (Sandbox Code Playgroud)

这是一个更高级的示例,涉及基于天的时间戳增量:

SELECT
    api_project.name,
    api_project.created,
    survey_response.created AS response_date,
    CASE
        WHEN survey_response.created
            BETWEEN api_project.created AND
                   (api_project.created + INTERVAL '180 days')
            THEN 'first_6_months'
        ELSE '6_months_after'
    END AS when_it_was_answered,
    EXTRACT(DAYS FROM survey_response.created - api_project.created)
      AS days_since_response
FROM
    bfb_survey_surveyresponseppent
Run Code Online (Sandbox Code Playgroud)