在Redshift中使用CTE和Update

时间:2018-03-26 19:31:26

标签: sql amazon-redshift common-table-expression

我正在将一些SQL逻辑从SSMS中使用的T-SQL转换为Amazon Redshift。 I believe Redshift is a fork of Postgres version 8.0.2所以除非使用Postgres 9.1,否则以下内容可能无法实现。

WITH CTE_ID AS 
(
SELECT FULL_NAME, COUNT(DISTINCT ID) as ID_COUNT, MAX(ID) AS MAX_ID
FROM MEMBERS
GROUP BY FULL_NAME
HAVING COUNT(DISTINCT ID) > 1
)
UPDATE a
SET a.ID = b.MAX_ID
FROM MEMBERS a
INNER JOIN CTE_ID b
ON a.FULL_NAME = b.FULL_NAME

如果Amazon Redshift不支持此功能,我最好的选择是创建一个新的“临时”表并用CTE生成的值填充它吗?

3 个答案:

答案 0 :(得分:2)

您可以将查询重写为派生表,如@a_horse_with_no_name所述:

UPDATE a
SET a.ID = b.MAX_ID
FROM MEMBERS a
INNER JOIN (
  SELECT FULL_NAME, COUNT(DISTINCT ID) as ID_COUNT, MAX(ID) AS MAX_ID
  FROM MEMBERS
  GROUP BY FULL_NAME
  HAVING COUNT(DISTINCT ID) > 1
  ) b
ON a.FULL_NAME = b.FULL_NAME

答案 1 :(得分:0)

创建一个临时表而不是with子句将起作用。

error_page 403=301 /your-403-app_offline.html;

答案 2 :(得分:0)

现有答案(包括已接受的答案)无效。这应该有效:

UPDATE members AS a
SET    id = b.max_id
FROM  (
   SELECT full_name, max(id) AS max_id
   FROM   members
   GROUP  BY full_name
   HAVING count(DISTINCT id) > 1
   ) b
WHERE  a.full_name = b.full_name
AND    a.id IS DISTINCT FROM b.max_id;

不需要 CTE(尽管可能)。子查询更简单。

目标表只列出一次。您只需在 FROM 子句中使用(不同的)别名重复它以满足特殊需要。

SET 列表中的目标列不能是表限定的。

未加引号的 names are folded to lower case in Redshift。大写拼写只会增加混乱。

我添加了谓词 AND a.id IS DISTINCT FROM b.max_id 以跳过不会更改的行的更新。 (昂贵的无操作。)您只希望那些在特殊情况下触发(未声明的)副作用。

Redshift manual for UPDATE 中的更多内容。