【问题标题】:postgresql - filter out double rows (but not the first and last one)postgresql - 过滤掉双行(但不是第一行和最后一行)
【发布时间】:2014-02-06 11:45:07
【问题描述】:

我遇到了“postgres”SQL 问题。

我有一张像这样的桌子

id 名称级别时间戳 1 皮特 1 100 2 皮特 1 200 3 皮特 1 500 4 皮特 5 900 7 皮特 5 1000 9 皮特 5 1200 15 皮特 2 700

现在我想删除我不需要的行。我只想现在他获得新级别的第一行和他拥有此级别的最后一行。

id 名称级别时间戳 1 皮特 1 100 3 皮特 1 500 15 皮特 2 700 4 皮特 5 900 9 皮特 5 1200

(还有更多列,例如领域点等)

如果时间戳只是增加,我有一个解决方案。

SELECT id, name, level, timestamp 
FROM player_testing 
WHERE id IN ( SELECT MAX(dup.id)
              FROM player_testing As dup
              GROUP BY dup.name, dup.level)
              UNION
              SELECT MIN(dup.id)
              FROM player_testing As dup
              GROUP BY dup.name, dup.level)
             )
ORDER BY ts

但我没有办法让它解决我的问题。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:
    select id, name, level, timestamp
    from (
      select id,name,level,timestamp,
             row_number() over (partition by name, level order by timestamp) as rn,
             count(*) over (partition by name, level) as max_rn
      from player_testing
    ) t
    where rn = 1 or rn = max_rn;
    

    顺便说一句:timestamp 是一个可怕的列名称。原因之一是因为它是一个保留字,但更重要的是因为它不记录该列包含的内容。那是start_timestampend_timestamp valid_until_timestamp,...?

    【讨论】:

    • 在我的表中是否调用 ts ;) 我只写了时间戳以明确该列中存储了哪种数据。
    • @user3279298 ts 老实说更糟糕 ;)
    【解决方案2】:

    这里是不带over partition 的@a_horse_with_no_name 的替代解决方案,因此是更通用的SQL:

    select * 
    from player_testing as A
    where id = (
      select min(id)
      from player_testing as B
      where A.name = B.name
      and A.level = B.level
      )
    or    id = (
      select max(id)
      from player_testing as B
      where A.name = B.name
      and A.level = B.level
      )
    

    这里是显示它工作的小提琴:http://sqlfiddle.com/#!2/47bd44/1

    【讨论】:

    • 很好的解决方案。但在这里我必须 A.xxx = B.xx 每列。我有很多。在 a_horse_with_no_name 解决方案上,我只需要列出列。问题是,哪个更快?我当时有 240 万行(并且只收集了几天)第一个解决方案大约需要 3 分钟才能找到(并在修改后)删除不需要的(双)行。我也要测试泛型。
    • 好的,第二个需要很长时间。在一张干净的桌子上(大约剩下 150k 行),第一个解决方案需要大约 5 秒来检查是否有双行。第二个 sql 查询仍在运行(现在大约 15 分钟)。我认为因为 sql server 必须检查 140k 行中的每一行是否存在具有相同值的最小值和最大值(id、ts 除外),因此它的比较值约为 140k * 2*140k。我不知道过度分区是如何工作的,但它要快得多。
    猜你喜欢
    • 1970-01-01
    • 2013-12-16
    • 2020-06-20
    • 1970-01-01
    • 2019-02-06
    • 2015-06-24
    • 2021-11-27
    • 2011-03-06
    • 2015-08-20
    相关资源
    最近更新 更多