从CTE中选择可能为null / undefined的

时间:2017-09-05 16:11:53

标签: sql postgresql common-table-expression

在Postgres 9.6中的函数/存储过程中我想从每个表中使用一个CTE从两个不同的表中获取数据,如下所示:

WITH "CTE_from_table1" AS (SELECT column1, column2 FROM table1 WHERE id = $1),
     "CTE_from_table2" AS (SELECT column1, column2 FROM table2 WHERE id = $2)
SELECT 
  COALESCE(
     "CTE_from_table1".column1,
     "CTE_from_table2".column1,    
     CASE WHEN "CTE_from_table1".column2 = 42 OR "CTE_from_table2".column2 = 42 
          THEN 'Something is 42' ELSE 'something else!' END
   )
FROM "CTE_from_table1","CTE_from_table2";

(列1和列2的数据类型对于两个表都是相同的:column1是文本,column2是整数。)

只要两个CTE都被定义,它就可以工作。问题是:参数$1和/或$2可以是null,也可以包含根本不存在的ID。在这种情况下,我希望结果something else!,因为前两个COALESCE参数评估为null,第三个参数CASE WHEN应该转到ELSE }}将返回something else!

这就是我的理论。但是,实际上,只要其中一个CTE未定义/为null,我就会得到null。我该怎么办?

1 个答案:

答案 0 :(得分:3)

您的问题是FROM子句中可怕的逗号。简单的规则。 。 。 从不FROM子句中使用逗号。在这种情况下,您需要一个"外部交叉连接"。逗号执行"内部交叉连接",因此如果CTE没有行,则不返回任何行。

很遗憾,OUTER CROSS JOIN并不存在,因此您可以使用FULL OUTER JOIN

WITH "CTE_from_table1" AS (SELECT column1, column2 FROM table1 WHERE id = $1),
     "CTE_from_table2" AS (SELECT column1, column2 FROM table2 WHERE id = $2)
SELECT COALESCE(ct1.column1, ct2.column1,    
                CASE WHEN 42 IN (ct1.column2, ct2.column2)
                     THEN 'Something is 42'
                     ELSE 'something else!'
                END
               )
FROM "CTE_from_table1" ct1 FULL OUTER JOIN
     "CTE_from_table2" ct2
     ON 1=1;

我不是混合CASECOALESCE()的忠实粉丝,所以我倾向于写:

SELECT (CASE WHEN ct1.column1 IS NOT NULL THEN ct1.column1
             WHEN ct2.column1 IS NOT NULL THEN ct2.column1 
             WHEN 42 IN (ct1.column2, ct2.column2) THEN 'Something is 42'
             ELSE 'something else!'
        END)