2016-08-22 40 views
2

我想在不改變業務邏輯的情況下簡化下面的sql代碼。在這裏我提到了我想修改的postgresql代碼。如何使用IF條件簡化SQL代碼。 (Postgresql)

SELECT IF(
    (SELECT `rate` FROM `vat_rate` WHERE '2017-05-12' BETWEEN from_date AND to_date) is not null , 
    (SELECT `rate` FROM `vat_rate` WHERE '2017-05-12' BETWEEN from_date AND to_date) , 

     IF((SELECT `rate` FROM `vat_rate` WHERE from_date is null and '2017-05-12' < to_date) is not null, 
      (SELECT `rate` FROM `vat_rate` WHERE from_date is null and '2017-05-12' < to_date), 

       IF(
        (SELECT `rate` FROM `vat_rate` WHERE to_date is null and '2017-05-12' > from_date) is not null, 
          (SELECT `rate` FROM `vat_rate` WHERE to_date is null and '2017-05-12' > from_date), 
          'not found' 
         ) 
      ) 
    ) as rate 
+5

SQL沒有'if'語句。反引號對於SQL標識符也是非法的。請[編輯]你的問題,並解釋你正試圖解決的實際_problem_(而不是向我們扔一堆無效的SQL),並添加一些樣本數據和基於這些數據的預期輸出。 _Formatted_文本,請[無屏幕截圖](http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-of-code-on-so-when-asking-a-問題/ 285557#285557) –

+1

注意:通過使用-infinity和+ infinity作爲from_date和to_date的默認值,可以避免這種混亂。 – joop

回答

2

你是Coalesce()操作後:

SELECT 
    COALESCE (
    (SELECT rate FROM vat_rate WHERE '2017-05-12' BETWEEN from_date AND to_date), 
    (SELECT rate FROM vat_rate WHERE from_date is null and '2017-05-12' < to_date), 
    (SELECT rate FROM vat_rate WHERE to_date is null and '2017-05-12' > from_date), 
    'not found' 
) as rate 
+1

效率依然不高。正如你所看到的,同一張桌子使用了3次。 – sagi

2

爲什麼不直接在vat_rate表使用CASE EXPRESSION,而不是遍地從中選擇每個價值?這裏有一個解決方案應該使用條件聚合來做同樣的事情:

SELECT COALESCE(t.val_1,t.val_2,t.val_3) as calc_col 
FROM (
    SELECT MAX(CASE WHEN vat_rate between from_date AND to_date THEN rate END) as val_1, 
      MAX(CASE WHEN from_date is null and '2017-05-12' < to_date THEN rate END) as val_2, 
      MAX(CASE WHEN to_date is null and '2017-05-12' > from_date THEN rate END) as val_3 
    FROM vat_rate) t 
3

複雜性是由允許日期中的NULL引起的。使用-infinity和(+)infinity作爲默認值將避免空日期的測試。更改表定義:

ALTER TABLE vat_rate 
     ALTER COLUMN from_date SET DEFAULT '-infinity' 
     , ALTER COLUMN to_date SET DEFAULT 'infinity' 
     ; 

UPDATE vat_rate SET from_date = DEFAULT WHERE from_date IS NULL; 
UPDATE vat_rate SET to_date = DEFAULT WHERE to_date IS NULL; 

ALTER TABLE vat_rate 
     ALTER COLUMN from_date SET NOT NULL 
     , ALTER COLUMN to_date SET NOT NULL 
     ; 

可以減少您的查詢剛:


SELECT rate AS the_reet 
FROM vat_rate 
WHERE '2017-05-12' BETWEEN from_date AND to_date 
       ; 

如果你不能改變表的定義,你可以摺疊裏面的日期值查詢:


SELECT rate AS the_reet 
FROM vat_rate 
WHERE '2017-05-12' BETWEEN COALESCE(from_date, '-infinity'::date) 
       AND COALESCE(to_date, 'infinity'::date) 
       ; 

避免聚結()(這可能是更快)

SELECT rate AS the_reet 
FROM vat_rate 
WHERE ('2017-05-12' >= from_date OR from_date IS NULL) 
AND ('2017-05-12' <= to_date OR to_date IS NULL) 
       ; 

極端情況下,不匹配範圍可以通過添加一個聯盟來解決。