如何使用 RANK 从 table 中过滤掉第一个和最后一个条目?
How to filter out the first and last entry from a table using RANK?
我有这个数据:
Id Date Value
'a' 2000 55
'a' 2001 3
'a' 2012 2
'a' 2014 5
'b' 1999 10
'b' 2014 110
'b' 2015 8
'c' 2011 4
'c' 2012 33
我想过滤掉 first 和 last 值(当 table 在 Date 列上排序时), 只保留其他值。如果只有两个条目,则不返回任何内容。 (Id 的示例 = 'c')
ID Date Value
'a' 2001 3
'a' 2012 2
'b' 2014 110
我尝试将 order by (RANK() OVER (PARTITION BY [Id] ORDER BY Date ...)) 与这篇文章 (http://blog.sqlauthority.com/2008/03/02/sql-server-how-to-retrieve-top-and-bottom-rows-together-using-t-sql/) 结合使用,但我无法做到工作。
[更新]
所有 3 个答案似乎都不错。但我不是 SQL 专家,所以我的问题是如果 table 有大约 800000 行并且任何列上都没有索引,那么哪个性能最快。
您可以使用 row_number
两次来确定 min
和 max
日期,然后进行相应的过滤:
with cte as (
select id, [date], value,
row_number() over (partition by id order by [date]) minrn,
row_number() over (partition by id order by [date] desc) maxrn
from data
)
select id, [date], value
from cte
where minrn != 1 and maxrn != 1
这是另一种使用 min
和 max
的方法,无需使用排名函数:
with cte as (
select id, min([date]) mindate, max([date]) maxdate
from data
group by id
)
select *
from data d
where not exists (
select 1
from cte c
where d.id = c.id and d.[date] in (c.mindate, c.maxdate))
这里有一个与 row_number
和 count
类似的解决方案:
SELECT id,
dat,
value
FROM (SELECT *,
ROW_NUMBER()
OVER(
partition BY id
ORDER BY dat) rnk,
COUNT(*)
OVER (
partition BY id) cnt
FROM @table) t
WHERE rnk NOT IN( 1, cnt )
你可以用 EXISTS
:
SELECT *
FROM Table1 a
WHERE EXISTS (SELECT 1
FROM Table1 b
WHERE a.ID = b.ID
AND b.Date < a.Date
)
AND EXISTS (SELECT 1
FROM Table1 b
WHERE a.ID = b.ID
AND b.Date > a.Date
)
演示:SQL Fiddle
我有这个数据:
Id Date Value
'a' 2000 55
'a' 2001 3
'a' 2012 2
'a' 2014 5
'b' 1999 10
'b' 2014 110
'b' 2015 8
'c' 2011 4
'c' 2012 33
我想过滤掉 first 和 last 值(当 table 在 Date 列上排序时), 只保留其他值。如果只有两个条目,则不返回任何内容。 (Id 的示例 = 'c')
ID Date Value
'a' 2001 3
'a' 2012 2
'b' 2014 110
我尝试将 order by (RANK() OVER (PARTITION BY [Id] ORDER BY Date ...)) 与这篇文章 (http://blog.sqlauthority.com/2008/03/02/sql-server-how-to-retrieve-top-and-bottom-rows-together-using-t-sql/) 结合使用,但我无法做到工作。
[更新]
所有 3 个答案似乎都不错。但我不是 SQL 专家,所以我的问题是如果 table 有大约 800000 行并且任何列上都没有索引,那么哪个性能最快。
您可以使用 row_number
两次来确定 min
和 max
日期,然后进行相应的过滤:
with cte as (
select id, [date], value,
row_number() over (partition by id order by [date]) minrn,
row_number() over (partition by id order by [date] desc) maxrn
from data
)
select id, [date], value
from cte
where minrn != 1 and maxrn != 1
这是另一种使用 min
和 max
的方法,无需使用排名函数:
with cte as (
select id, min([date]) mindate, max([date]) maxdate
from data
group by id
)
select *
from data d
where not exists (
select 1
from cte c
where d.id = c.id and d.[date] in (c.mindate, c.maxdate))
这里有一个与 row_number
和 count
类似的解决方案:
SELECT id,
dat,
value
FROM (SELECT *,
ROW_NUMBER()
OVER(
partition BY id
ORDER BY dat) rnk,
COUNT(*)
OVER (
partition BY id) cnt
FROM @table) t
WHERE rnk NOT IN( 1, cnt )
你可以用 EXISTS
:
SELECT *
FROM Table1 a
WHERE EXISTS (SELECT 1
FROM Table1 b
WHERE a.ID = b.ID
AND b.Date < a.Date
)
AND EXISTS (SELECT 1
FROM Table1 b
WHERE a.ID = b.ID
AND b.Date > a.Date
)
演示:SQL Fiddle