日期为params的函数可以为NULL

时间:2014-11-25 09:34:19

标签: sql postgresql null date-range postgresql-9.3

我正在尝试在PostgreSQL 9.3.5中实现一个日期作为参数的函数 它应涵盖以下所有条件并相应地返回结果。

select * from tablename
where sid is not null and dob >= '11-14-2014' order by dob;
-- Only Start Date

select * from tablename
where sid is not null and dob <= '11-21-2014' order by dob;
-- Only End Date

select * from tablename
where sid is not null and dob between '11-10-2014' and '11-21-2014' order by dob; 
-- Both Start and End Dates are Given

select * from tablename
where sid is not null and dob is null; 
-- Both Start and End Dates are Null

SQL Fiddle

但我上面的SQL Fiddle没有按预期工作。

我希望有一个通用实现,这样如果明天我在标准搜索中有更多new Date Fields,那么我可以将它们添加到where condition中,但不能添加到IF的每一行中1}}陈述。

Updated SQL Fiddle

3 个答案:

答案 0 :(得分:1)

这可以 更简单

您可以简化@ Clodoaldo目前接受的答案:

SELECT *
FROM   sampletest
WHERE  eid IS NOT NULL
AND   (_sd IS NULL AND _ed IS NULL OR
       _sd IS NULL AND dob <= _ed  OR
       _ed IS NULL AND dob >= _sd  OR
       dob BETWEEN _sd AND _ed);
  • 比较dob >= _sd后,无需另外检查_sd is not null 无论如何,表达式只能评估为TRUE非空_sd

但这些都不是必要的:

CREATE OR REPLACE FUNCTION test_dob_dates(_sd date, _ed date)
  RETURNS SETOF sampletest AS
$func$
SELECT *
FROM   sampletest
WHERE  eid IS NOT NULL
AND    dob BETWEEN COALESCE(_sd, -infinity) AND COALESCE(_ed, infinity)
$func$ LANGUAGE sql STABLE;

SQL Fiddle(第9.3页)。

除此之外:我建议使用标准ISO日期 '2014-11-10' ,而不是 '11-10-2014' ,这可能是不明确的,并打破了不同的区域设置设置。 The manual advises as much.

答案 1 :(得分:0)

您必须将函数定义为返回set of sampletest,然后根据传递的参数返回return different query restults

CREATE FUNCTION
  test_dob_dates(_sd date, _ed date)
RETURNS
  SETOF sampletest
AS
  $BODY$
    BEGIN
      IF _sd IS NOT NULL AND _ed IS NOT NULL THEN
        RETURN QUERY SELECT * FROM sampletest WHERE dob BETWEEN _sd AND _ed;
      ELSIF _sd IS NULL AND _ed IS NULL THEN
        RETURN QUERY SELECT * FROM sampletest WHERE dob IS NULL;
      ELSEIF _ed IS NOT NULL THEN
        RETURN QUERY SELECT * FROM sampletest WHERE dob <= _ed;
      ELSE
        RETURN QUERY SELECT * FROM sampletest WHERE dob >= _sd;
      END IF;
    END;
  $BODY$
LANGUAGE
  'plpgsql' VOLATILE;

eid IS NOT NULL子句似乎是多余的,因为您已将eid定义为PRIMARY KEY,这意味着它永远不会为NULL。

答案 2 :(得分:0)

SQL Fiddle

create function test_dob_dates(_sd date, _ed date)
returns setof sampletest as $body$
    select *
    from sampletest
    where
        eid is not null
        and (
            (_sd is null and _ed is null)
            or (_sd is not null and _ed is null and dob >= _sd)
            or (_sd is null and _ed is not null and dob <= _ed)
            or dob between _sd and _ed
        );
$body$ language sql stable;
相关问题