postgresql - 过滤掉双行(但不是第一行和最后一行)

时间:2014-02-06 11:45:07

标签: sql postgresql

我遇到了“postgres”SQL问题。

我有一张看起来像这样的桌子

  id          name          level          timestamp 
   1          pete          1              100 
   2          pete          1              200 
   3          pete          1              500 
   4          pete          5              900 
   7          pete          5              1000 
   9          pete          5              1200 
  15          pete          2              700 

现在我想删除我不需要的行。我现在只想要他获得新等级的第一行,以及他拥有这个等级的最后一行。

  id          name          level          timestamp 
   1          pete          1              100 
   3          pete          1              500 
  15          pete          2              700 
   4          pete          5              900 
   9          pete          5              1200

(还有更多列,如realmpoints等)

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

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

但我发现无法让它解决我的问题。

2 个答案:

答案 0 :(得分:2)

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,......?

答案 1 :(得分:0)

这是@ a_horse_with_no_name没有over partition的替代解决方案,因此更通用的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