为什么我不能在此查询中使用WITH(公用表表达式)?

时间:2014-01-22 12:42:45

标签: sql postgresql common-table-expression

这只是一个SSCCE:

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 个答案:

答案 0 :(得分: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 ;

SQL-Fiddle

进行测试

答案 1 :(得分: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内部选择的列提供一个别名。

答案 2 :(得分: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;