按连续等值组排名

问题描述 投票:0回答:2

通过此查询:

with tbl as
(
  select  1 ord, 'A' name from dual
  union all
  select  2 ord, 'A' name from dual
  union all
  select  3 ord, 'A' name from dual
  union all
  select  4 ord, 'B' name from dual
  union all
  select  5 ord, 'B' name from dual
  union all
  select  6 ord, 'A' name from dual
  union all
  select  7 ord, 'A' name from dual
  union all
  select  8 ord, 'C' name from dual
  union all
  select  9 ord, 'C' name from dual
  union all
  select 10 ord, 'B' name from dual
  union all
  select 11 ord, 'B' name from dual
  union all
  select 12 ord, 'B' name from dual
) 
select ord, name, myrank(...)
from tbl
order by
  ord;

我想得到这些结果:

       ORD NAME     MYRANK
---------- ---- ----------
         1 A             1
         2 A             1
         3 A             1
         4 B             2
         5 B             2
         6 A             3
         7 A             3
         8 C             4
         9 C             4
        10 B             5
        11 B             5
        12 B             5

连续相等的值具有相同的排名。 相同连续相等值的不同组具有不同的等级。 排名按“ord”顺序单调增加。

对于 Oracle 和 PostgreSQL(最好对两个系统进行最终查询)。

sql postgresql oracle rank gaps-and-islands
2个回答
1
投票

从 Oracle 12 开始,您可以使用

MATCH_RECOGNIZE
执行逐行模式匹配:

SELECT ord, name, myrank
FROM   tbl
MATCH_RECOGNIZE(
  ORDER BY ord
  MEASURES
    MATCH_NUMBER() AS myrank
  ALL ROWS PER MATCH
  PATTERN (same_name+)
  DEFINE
    same_name AS FIRST(name) = name
);

在所有版本中,您可以使用

LAG
SUM
分析函数来输出相同的结果:

SELECT ord,
       name,
       SUM(has_changed) OVER (ORDER BY ord) AS myrank
FROM   (
  SELECT ord,
         name,
         CASE
         WHEN name = LAG(name) OVER (ORDER BY ord)
         THEN 0
         ELSE 1
         END AS has_changed
  FROM   tbl
) t;

对于样本数据,两者输出:

ORD 姓名 MYRANK
1 A 1
2 A 1
3 A 1
4 B 2
5 B 2
6 A 3
7 A 3
8 C 4
9 C 4
10 B 5
11 B 5
12 B 5

第二个查询也适用于 PostgreSQL。

Oracle 小提琴 PostgreSQL 小提琴


0
投票

这适用于任一 RDBMS:

SELECT ord, name
     , count(step or NULL) OVER (ORDER BY ord) AS myrank
FROM  (
   SELECT ord, name, name <> lag(name) OVER (ORDER BY ord) AS step
   FROM   tbl
   ) sub;

Postgres 小提琴
甲骨文小提琴

值得注意的是,

count()
仅计算非空值,并且

true  OR null → true
false OR null → null

计算

name
列中的更改数量会生成所需的组编号。

针对 Postgres 进行了优化:

SELECT ord, name
     , count(*) FILTER (WHERE step) OVER (ORDER BY ord) + 1 AS myrank
FROM  (
   SELECT *, name <> lag(name) OVER (ORDER BY ord) AS step
   FROM   tbl
   ) sub;

相关:

© www.soinside.com 2019 - 2024. All rights reserved.