2016-08-22 36 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) 
       ; 

极端情况下,不匹配范围可以通过添加一个联盟来解决。