【问题标题】:SQL: Ignore some returned rows, deleting othersSQL:忽略一些返回的行,删除其他的
【发布时间】:2012-10-11 16:26:32
【问题描述】:

我有这张桌子:

| Column        | Type                           |
+---------------+--------------------------------+         
| id            | integer                        |
| recipient_id  | integer                        | 
| is_read       | boolean                        | 
| updated_at    | timestamp(0) without time zone | 

我必须使用此特定规则从该表中删除项目:

  • 对于每个recipient_id,我们保留最后阅读的 5 个条目,并删除旧的阅读条目。

我试图用RECURSIVE WITH 声明来改变主意,但惨遭失败。我已经以编程方式实现了我的解决方案,但我想知道是否有一个像样的纯 SQL 解决方案。

【问题讨论】:

    标签: sql postgresql window-functions


    【解决方案1】:
    DELETE FROM tbl t
    USING (
        SELECT id, row_number() OVER (PARTITION BY recipient_id
                                      ORDER BY updated_at DESC) as rn
        FROM   tbl
        WHERE  is_read
      ) x
    WHERE  x.rn > 5
    AND    x.id = t.id;
    

    JOIN 通常比 IN 表达式快,尤其是在项目数量较多的情况下。
    并使用row_number(), not rank()

    【讨论】:

      【解决方案2】:

      查看window functions:

      DELETE FROM table
      WHERE id IN (
        SELECT id
        FROM (
          SELECT id, rank() OVER (PARTITION BY recipient_id ORDER BY updated_at DESC) as position
          FROM table
          WHERE is_read
        ) subselect WHERE position > 5
      )
      

      【讨论】:

        【解决方案3】:
        delete from t
        where id in (
            select id
            from (
                select 
                    id, 
                    row_number() over(partition by recipient_id order by updated_at desc) rn
                from t
                where is_read
            ) s
            where s.rn > 5
        )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-24
          • 2022-04-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多