2017-09-05 31 views
0

内部中的Postgres 9.6我想用一个CTE为每个表像这样抓住从两个不同的表的数据的功能/存储过程:从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列是相同的:第1列是文本,第2列是整数。)

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

这就是我的理论。但是,实际上,只要其中一个CTE未定义/ null,我就会得到null。我能做些什么?

+0

你可以加入表1和表2吗? –

+0

交叉连接到空数据集将生成空数据集。所以你需要每张表总是返回至少一条记录。你可以在col1,col2的记录中加入一个特殊值,并在case语句中处理它......用CTE1作为(从table1中选择column1,column2,其中code <'00100'U NION ALL选择'-1', -1)' – xQbert

回答

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)