postgresql Postgres日期检查- is_date fn短路

kyvafyod  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(275)

我在表中有一组记录,其中一些记录的日期无效。我想忽略这些无效记录,并检查其余记录。我构建了如下查询,但发现它不起作用。

select * from tbl_name i
             where is_date(i.dob) and i.dob::date > CURRENT_DATE;

我知道sql不会短路,所以它也会考虑无效的记录,并以超出范围的日期/时间结束。请帮助我以一种可以消除无效日期并仅对有效日期进行日期比较的方式修改此查询。

3wabscal

3wabscal1#

在Postgres中不能保证短路。无论是在“普通”WHERE子句中,还是在使用派生表(from (select ...) where ...)时,都不能保证短路。强制在两个步骤中求值的一种方法是物化公用表表达式:

with data as materialized (
  select * 
  from tbl_name i
  where is_date(i.dob)
)
select *
from data
where dob::date > CURRENT_DATE;

materialized关键字可防止优化程序将外部查询的条件推入CTE。
显然,这是假设is_date()永远不会返回误报

lmvvr0a8

lmvvr0a82#

WHERE中使用CASE来区分有效日期和无效日期,并运行>比较以确定有效日期,否则返回FALSE

create or replace function is_date(s varchar) returns boolean as $$
begin
  if s is null then
     return false;
  end if;
  perform s::date;
  return true;
exception when others then
  return false;
end;
$$ language plpgsql;

create table date_str (id integer, dt_str varchar);

insert into date_str values (1, '2022-11-02'), (2, '1234'), (3, '2022-12-03');
insert into date_str values (4, 'xyz'), (5, '2022-01-01'), (6, '2023-02-02');

select * from date_str;
 id |   dt_str   
----+------------
  1 | 2022-11-02
  2 | 1234
  3 | 2022-12-03
  4 | xyz
  5 | 2022-01-01
  6 | 2023-02-02

select current_date;
 current_date 
--------------
 11/02/2022

SELECT
    *
FROM
    date_str
WHERE
    CASE WHEN is_date (dt_str) = 't' THEN
        dt_str::date > CURRENT_DATE
    ELSE
        FALSE
    END;

 id |   dt_str   
----+------------
  3 | 2022-12-03
  6 | 2023-02-02

相关问题