Oracle SQL条件排名

时间:2018-08-17 12:12:16

标签: sql oracle ranking rank

在我的查询中,我正在执行多种类型的排名,并且对于一种排名类型,仅当某些列不为null时,才希望对行进行排名。否则我不希望排名发生。

例如,这是一个示例表:

+------+------------+------------+--------+--------+
| col1 |    col2    |    col3    | rank 1 | rank 2 |
+------+------------+------------+--------+--------+
| a    | 2018-01-20 | 2018-03-04 |      2 | 2      |
| a    | 2018-01-24 | 2018-04-04 |      1 | 1      |
| b    | 2018-01-02 | 2018-05-03 |      1 | 1      |
| c    | 2017-01-02 | 2017-05-08 |      3 | 2      |
| d    | 2016-05-24 | null       |      1 | null   |
| c    | 2018-02-05 | 2018-05-03 |      2 | 1      |
| c    | 2018-07-28 | null       |      1 | null   |
+------+------------+------------+--------+--------+

rank1是根据partition by col1 order by col2 desc计算得出的 排名2的计算方法应相同,但仅当col3为null时,否则应为null。

如何在单个查询中同时获得两个排名?我尝试对rank2使用case语句,但是当col3为null时,它将跳过排名,

2 个答案:

答案 0 :(得分:1)

如果我理解正确,可以尝试将CASE WHENsum一起使用窗口功能

CASE WHEN检查col3是否null是否累积,否则显示NULL

CREATE TABLE T(
  col1 VARCHAR(5),
  col2 DATE,
  col3 DATE
);

INSERT INTO T VALUES ( 'a' , to_date('2018-01-20','YYYY-MM-DD') , to_date('2018-03-04','YYYY-MM-DD'));  
INSERT INTO T VALUES ( 'a' , to_date('2018-01-24','YYYY-MM-DD') , to_date('2018-04-04','YYYY-MM-DD'));  
INSERT INTO T VALUES ( 'b' , to_date('2018-01-02','YYYY-MM-DD') , to_date('2018-05-03','YYYY-MM-DD'));  
INSERT INTO T VALUES ( 'c' , to_date('2017-01-02','YYYY-MM-DD') , to_date('2017-05-08','YYYY-MM-DD'));  
INSERT INTO T VALUES ( 'd' , TO_DATE('2016-05-24','YYYY-MM-DD') , null);  
INSERT INTO T VALUES ( 'c' , TO_DATE('2018-02-05','YYYY-MM-DD') , to_date('2018-05-03','YYYY-MM-DD'));  
INSERT INTO T VALUES ( 'c' , TO_DATE('2018-07-28','YYYY-MM-DD') , null);  

查询1

select t1.*,
    rank() OVER(partition by col1 order by col2 desc) rank1,
    (CASE WHEN COL3 IS NOT NULL THEN
       SUM(CASE WHEN COL3 IS NOT NULL THEN 1 ELSE 0 END) OVER(partition by col1 order by col2 desc)
    ELSE
       NULL
    END) rank2
FROM T t1

Results

| COL1 |                 COL2 |                 COL3 | RANK1 |  RANK2 |
|------|----------------------|----------------------|-------|--------|
|    a | 2018-01-24T00:00:00Z | 2018-04-04T00:00:00Z |     1 |      1 |
|    a | 2018-01-20T00:00:00Z | 2018-03-04T00:00:00Z |     2 |      2 |
|    b | 2018-01-02T00:00:00Z | 2018-05-03T00:00:00Z |     1 |      1 |
|    c | 2018-07-28T00:00:00Z |               (null) |     1 | (null) |
|    c | 2018-02-05T00:00:00Z | 2018-05-03T00:00:00Z |     2 |      1 |
|    c | 2017-01-02T00:00:00Z | 2017-05-08T00:00:00Z |     3 |      2 |
|    d | 2016-05-24T00:00:00Z |               (null) |     1 | (null) |

答案 1 :(得分:0)

我想您可能想要:

select count(col3) over (partition by col1 order by col2 desc)

请注意,这等效于row_number()而不是rank()。对于您的数据,这些是等效的。