【问题标题】:How to do an update based on a count - SQL (postgres)如何根据计数进行更新 - SQL (postgres)
【发布时间】:2009-08-10 12:47:06
【问题描述】:

我有一张桌子,我们称之为“条目”,看起来像这样(简化):

id [pk]
user_id [fk]
created [date]
processed [boolean, default false]

并且我想创建一个 UPDATE 查询,它将所有条目上的处理标志设置为 true,除了每个用户的最新 3 个(就创建的列而言是最新的)。因此,对于以下条目:

1,456,2009-06-01,false
2,456,2009-05-01,false
3,456,2009-04-01,false
4,456,2009-03-01,false

只有条目 4 会将其已处理标志更改为 true。

有人知道我该怎么做吗?

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    我不知道 postgres,但这是标准 SQL,可能对您有用。

    update entries set
      processed = true
    where (
      select count(*)
      from entries as E
      where E.user_id = entries.user_id
      and E.created > entries.created
    ) >= 3
    

    换句话说,只要在以后的日期有三个或更多相同 user_id 的条目,就将已处理的列更新为 true。我假设 [created] 列对于给定的 user_id 是唯一的。如果不是,您将需要一个额外的标准来确定您所说的“最新”的含义。

    在 SQL Server 中你可以这样做,这更容易理解并且可能会更有效地执行:

    with T(id, user_id, created, processed, rk) as (
      select
        id, user_id, created, processed,
        row_number() over (
          partition by user_id
          order by created desc, id
        )
      from entries
    )
      update T set
        processed = true
      where rk > 3;
    

    更新 CTE 是一项非标准功能,并非所有数据库系统都支持 row_number。

    【讨论】:

    • 是的,您的 SQL 查询运行良好。我确实尝试过做这样的事情,但它对我不起作用。我不确定,因为我没有保留该查询,但我想我出于某种原因试图在子查询中选择 count(*), user_id,但我不知道我为什么会这样做。
    • 谢谢。顺便说一句,在阅读了 depesz 的解决方案后,我将 > 更改为 >=,这和我的一样,除了正确之外。 :) 确保你不要保留我原来的错误。
    【解决方案2】:

    首先,让我们从列出所有要更新的行的查询开始:

    select e.id
    from entries as e
    where (
        select count(*)
        from entries as e2
        where e2.user_id = e.user_id
            and e2.created > e.created
    ) > 2
    

    这会列出所有记录的 id,这些记录有超过 2 条 user_id 相同但创建时间晚于要返回的行中创建的记录。

    也就是说,它将列出所有记录,但每个用户最后 3 个。

    现在,我们可以:

    update entries as e
    set processed = true
    where (
        select count(*)
        from entries as e2
        where e2.user_id = e.user_id
            and e2.created > e.created
    ) > 2;
    

    想到一件事——它可能很慢。在这种情况下,使用自定义聚合或(如果您使用的是 8.4)窗口函数可能会更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-24
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      • 2021-05-01
      • 1970-01-01
      相关资源
      最近更新 更多