我有这些数据:
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
我想过滤掉第一个和 last 值(当表在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专家,所以我的问题是如果表有大约800000行并且任何列都没有索引,哪一个具有最快的性能。
答案 0 :(得分:1)
您可以使用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))
答案 1 :(得分:1)
以下是与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 )
答案 2 :(得分:0)
您可以使用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