简体   繁体   English

从CTE中选择,可能为空/未定义

[英]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 )应转到其ELSEELSE将返回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: 我不太喜欢混合使用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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM