[英]SELECT from CTEs which might be null/undefined
Inside a function/stored procedure in Postgres 9.6 I want to grab data from two different tables using one CTE for each table like so: 在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";
(Data type of column1 and column2 are resp. identical for both tables: column1 being a text, column2 an integer.) (两个表的column1和column2的数据类型分别相同:column1是文本,column2是整数。)
That works as long as both CTEs are defined. 只要定义了两个CTE,它就起作用。 The problem is: The parameters
$1
and/or $2
could be null
or could contain IDs which are simply not there. 问题是:参数
$1
和/或$2
可以为null
或者可以包含不存在的ID。 In this case, I expect the result something else!
在这种情况下,我希望结果会
something else!
, because the first two COALESCE
parameters evaluate to null
and the third, being the CASE WHEN
, should go to its ELSE
which would return something else!
,因为前两个
COALESCE
参数求值为null
,而第三个参数(为CASE WHEN
)应转到其ELSE
, ELSE
将返回something else!
. 。
That's my theory. 那是我的理论。 However, in practice I get
null
as soon as one of the CTEs is undefined/null. 但是,实际上,一旦其中一个CTE未定义/为
null
,我就会为空。 What can I do about that? 我该怎么办?
Your problem is the dreaded comma in the FROM
clause. 您的问题是
FROM
子句中令人恐惧的逗号。 Simple rule . 简单的规则。 .
。 .
。 Never use commas in the
FROM
clause. 请勿在
FROM
子句中使用逗号。 In this case, you want an "outer cross join". 在这种情况下,您需要“外部交叉连接”。 The comma does an "inner cross join", so no rows are returned if either CTE has no rows.
逗号执行“内部交叉连接”,因此如果任一CTE没有行,则不返回任何行。
Unfortunately, OUTER CROSS JOIN
doesn't exist, so you can make do with FULL OUTER JOIN
: 不幸的是,
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;
I'm not a big fan of mixing CASE
and COALESCE()
, so I'd be inclined to write: 我不太喜欢混合使用
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.