2014-01-22 87 views
1

这只是一个SSCCE:为什么我不能在此查询中使用WITH(公用表表达式)?

CREATE TABLE test(i INTEGER NOT NULL); 

WITH max_i AS (SELECT MAX(i) FROM test) 
SELECT * FROM test WHERE max_i - i < 2 AND max_i!=i 

PostgreSQL的抱怨:

ERROR: column "max_i" does not exist 

我想这是因为max_i是一个值,而不是一个行集,但我如何才能在一次定义我通过复杂查询获得的查询值,而不必在使用子查询时重复子查询?

回答

3

您在“最终”选择语句中根本没有引用CTE。因此你不能引用它。此外where条件需要引用不是表格。

在你的声明max_i是一个“表”的名称,因此它不能在where条件中使用。

WITH t_max AS (
    SELECT MAX(i) as max_i FROM test 
) 
SELECT * 
FROM test 
    CROSS JOIN t_max as t 
WHERE t.max_i - test.i < 2 
    AND t.max_i <> test.i; 

cross join不会做任何伤害,因为我们知道CTE(命名为t_max)将总是返回只有一行。

一旦您可以在最终选择中引用CTE,比较很容易,但要做到这一点,您需要为CTE内部选择的列提供别名。

1

我认为这是你在找什么

CREATE TABLE test(i INTEGER NOT NULL); 

WITH max_i AS (SELECT MAX(i) Mi FROM test) 
SELECT * FROM test 
JOIN max_i 
on max_i.Mi - 1 = test.i; 
5

首先,你不需要WHERE子句中这两个条件。该i = max_id - 1就足够了(如果它的工作。)

要从CTE使用的值,你要么必须使用(交叉)加入作为其他的答案或使用(不常见)语法:

WITH max_i AS 
    (SELECT MAX(i) FROM test) 
SELECT * 
FROM test 
WHERE i = (TABLE max_i) - 1 ; 

Test at SQL-Fiddle

+1

有趣。我不知道你可以使用'table'语法(这是'select * from'的缩写)作为标量值。 –

+1

+1为改善我的回答 –

+0

关于不需要这两个条件,是的,这是一个SSCCE我只是想动机的情况下,一个*可能*不得不参考表达不止一次。 –

相关问题