0

感谢您花时间看我的问题。我见过类似的问题,但深度不同。请帮忙!

我想更新包含 user_id 和 date_created 的表中所有行的列,其中 user_id 的 date_created 最低。

以下选择为我提供了我想要更新的所有行:

select user_id, min(date_created) from mytable s1 where 
    (select count(1) from mytable s2 where 
        s1.user_id = s2.user_id group by s2.user_id) 
 > 1 group by user_id order by user_id;

我本来希望这个更新能够工作:

update mytable set join_status = 1 where date_created = 
    (select min(date_created) from mytable s1 where 
        (select count(1) from simplepay_payment s2 where 
            s1.user_id = s2.user_id group by s2.user_id)
  > 1 group by user_id);

但是给出了以下错误:

ERROR:  more than one row returned by a subquery used as an expression

我尝试了几种不同的解决方案,但似乎没有任何帮助。

有人对我有什么想法吗?

再次感谢。

4

1 回答 1

3

将您的 SQL 更改为:

update mytable set join_status = 1 where date_created IN
    (select min(date_created) from mytable s1 where 
        (select count(1) from simplepay_payment s2 where 
            s1.user_id = s2.user_id group by s2.user_id)
  > 1 group by user_id);

在文档中阅读有关行比较的更多信息。


编辑:

在您正在执行的子查询中GROUP BY user_id。这意味着您收到许多行,具体取决于simplepay_payment表中唯一 user_id 值的数量。

为了使您的查询按预期工作,您应该使用 2 列加入:user_iddate_created. 正如您所提到的,您已经有了可以为您提供正确结果的查询,因此您可以像这样使用它:

WITH desired AS (
  SELECT user_id, min(date_created) AS mindt
    FROM mytable s1 where 
      (SELECT count(1) FROM mytable s2
        WHERE s1.user_id = s2.user_id GROUP BY s2.user_id) > 1
   GROUP BY user_id)
UPDATE mytable m SET join_status = 1 FROM desired d
 WHERE d.user_id = m.user_id AND d.mindt = m.date_created;

我已将您的查询包装到公用表表达式中并在UPDATE语句中使用它。您可以RETURNING m.*在查询末尾添加以查看已更新的行及其新值。

您可以在SQL Fiddle上测试此查询。


编辑2:

UPDATE公用表表达式(WITH 查询)在 9.1 版之前对语句不可用。您可以简单地将 CTE 子查询移动到更新中,如下所示:

UPDATE mytable m SET join_status = 1 FROM (
  SELECT user_id, min(date_created) AS mindt
    FROM mytable s1 where 
      (SELECT count(1) FROM mytable s2
        WHERE s1.user_id = s2.user_id GROUP BY s2.user_id) > 1
   GROUP BY user_id) d
 WHERE d.user_id = m.user_id AND d.mindt = m.date_created;
于 2012-05-16T19:26:16.567 回答