Oracle SQL:获取带过滤器的第一行

时间:2013-06-07 06:57:21

标签: sql oracle

如何让第一行过滤掉一些值?我使用row_number()(按名称ORDER BY Date分区)来获取订单(参见下面的示例)。但是我需要,等级将从Type = B的最后一次出现开始(见预期输出)

SELECT Name, Age, Type, Date, 
       row_number() over(partition by Name ORDER BY Date) as Rank
FROM TableA;

例如:

Name   Age   Type   Date          Rank
Ben    12      A    2013/02/01    1 
Rod    14      A    2013/02/05    2
Zed    13      B    2013/03/09    3
Ken    12      A    2013/04/02    4 
Jed    14      B    2013/05/01    5
Mar    13      A    2013/05/04    6
Nic    12      A    2013/06/02    7
Jen    15      A    2013/06/09    8

预期产出:

Name   Age    Type   Date         Rank
Mar    13      A    2013/05/04    1
Nic    12      A    2013/06/02    2
Jen    15      A    2013/06/09    3

4 个答案:

答案 0 :(得分:4)

尝试

WITH qry AS 
(
  SELECT "Name", "Age", "Type", "Date", 
         ROW_NUMBER() OVER (PARTITION BY "Type" ORDER BY "Date") rank
  FROM TableA
)
SELECT "Name", "Age", "Type", "Date"
  FROM qry
 WHERE rank = 1

输出:

| NAME | AGE | TYPE |                            DATE |
-------------------------------------------------------
|  Ben |  12 |    A | February, 01 2013 00:00:00+0000 |
|  Zed |  13 |    B |    March, 09 2013 00:00:00+0000 |

这是 SQLFiddle 演示

答案 1 :(得分:2)

还有另一种可能性:你可以将它包装在子查询中:

select
    t.*
  from
    (SELECT "Name", "Age", "Type", "Date", 
         ROW_NUMBER() OVER (PARTITION BY "Type" ORDER BY "Date") rank
       FROM TableA
     ) t
  where
    rank = 1

“子查询”和“公用表表达式with)”的行为有所不同,因此请看一下这些方法。这取决于你的情况,如果一个是强制性的(处理副作用)或一个更快。如果是Oracle,则会有materialize提示。 “按照SQL标准,CTE提供优化围栏功能”(这是here的改编引用)。

答案 2 :(得分:0)

试试这个:

SELECT Name, Age, Type, Date, 
       row_number() over(partition by Name ORDER BY Date) as Rank
FROM TableA
WHERE type <> 'B'
AND Date > (
    SELECT max(Date)
    FROM TableA
    WHERE type = 'B'
);

请注意,这假设与最后一个B完全相同的日期/时间没有A.

答案 3 :(得分:0)

这也应该按照你的要求做到:

select t.*,
       row_number() over(partition by "Name" ORDER BY "Date") as Rank
from  TableA t
where "Date" >= (select max("Date") from TableA where "Type" = 'B')