2014-11-25 54 views
3

我想在PostgreSQL 9.3.5中以日期爲參數實現一個函數。
它應該涵蓋以下所有條件並相應地返回結果。作爲參數可以爲NULL的日期函數

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小提琴是行不通的。

我希望有一個通用的實現,因此如果明天我有更多new Date Fields到標準搜索,然後我就可以在where condition添加它們,而不是在IF聲明每一行。

Updated SQL Fiddle

+1

爲什麼你需要一個單獨的功能?你所有的上述查詢似乎都是你想要的。一個單獨的函數似乎有點太多,因爲它看起來像查詢處理它很好,更可讀。 – DrColossos 2014-11-25 10:24:03

+0

@DrColossos我需要一個函數,因爲我試圖根據傳遞的參數(基於標準)來獲取細節,所以我想讓它們變成一個函數,以便我可以使用該函數返回結果作爲單行查詢。 – 09Q71AO534 2014-11-25 10:26:23

回答

1

這可能是簡單得多還是

您可以從@ Clodo阿爾的目前接受的答案簡化表達式:

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.

+0

對於無限,並讓我更好地瞭解時間複雜性。 :) 謝謝 – 09Q71AO534 2014-11-25 14:21:11

0

你必須定義函數爲返回set of sampletest然後return different query restults基於傳遞的參數。因爲你已經定義eid是一個主鍵,這意味着它不能爲NULL

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條款似乎是多餘的。

+0

上面的代碼是否最佳,並在最佳時間執行。我看到有多行代碼重複。請糾正我,如果我錯了。 – 09Q71AO534 2014-11-25 10:57:37

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; 
+0

感謝您的迴應:) – 09Q71AO534 2014-11-25 10:58:11

+0

我發現#Erwin Brandstetter發表了一些關於無限(某些特殊值)使用的理解。希望它是有用的 – 09Q71AO534 2014-11-25 14:23:36