在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
。我该怎么办?
答案 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;
我不是混合CASE
和COALESCE()
的忠实粉丝,所以我倾向于写:
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)