我如何在像MySQL这样的Oracle中编写等级sql

问题描述

我在MysqL中的sql段:

SELECT t.*,@r1:=@r1+1 r1,@r:=IF(@v=score OR(@v IS NULL AND score IS NULL),@r,@r1) rank,@v:=score v1 
FROM(SELECT @r :=0) a,(SELECT @r1 :=0) b,(SELECT @v:=NULL) v,(SELECT id,score FROM exam_inst 
WHERE eid = '1161918326813872128' AND type = 2 GROUP BY dealer 
ORDER BY i_level DESC,create_date DESC) t ORDER BY score DESC

我想在oracle中编写相同的查询sql,我该怎么办?

表:

A     B
c1    a
c1    b
c1    a
c2    a
c2    a
c2    b

查询结果:

A     B    R
c1    a    1
c1    b    2
c1    a    3
c2    a    1
c2    a    1
c2    b    3

解决方法

使用RANK分析函数:

SELECT t.*,RANK() OVER ( PARTITION BY a ORDER BY b ) AS r
FROM   table_name t;

或您的样本数据:

CREATE TABLE table_name ( a,b ) AS
SELECT 'c1','a' FROM DUAL UNION ALL
SELECT 'c1','b' FROM DUAL UNION ALL
SELECT 'c1','a' FROM DUAL UNION ALL
SELECT 'c2','b' FROM DUAL;

这将输出:

A  | B  |  R
:- | :- | -:
c1 | a  |  1
c1 | a  |  1
c1 | b  |  3
c2 | a  |  1
c2 | a  |  1
c2 | b  |  3

db 提琴here


更新

我只想比较相邻的行,我不在乎有多少个“ a”

SQL中的行是无序的;因此您将需要另一列来存储行的顺序:

CREATE TABLE table_name ( a,b,c ) AS
SELECT 'c1','a',1 FROM DUAL UNION ALL
SELECT 'c1','b',2 FROM DUAL UNION ALL
SELECT 'c1',3 FROM DUAL UNION ALL
SELECT 'c2',1 FROM DUAL UNION ALL
SELECT 'c2',2 FROM DUAL UNION ALL
SELECT 'c2',3 FROM DUAL;

这将找到行的密集行:

SELECT a,c,SUM( has_changed ) OVER ( PARTITION BY a ORDER BY c ) AS r
FROM   (
  SELECT t.*,CASE
         WHEN b = LAG( b ) OVER ( PARTITION BY a ORDER BY c )
         THEN 0
         ELSE 1
         END AS has_changed
  FROM   table_name t
)
ORDER BY a,c;

哪个输出:

A  | B  |  C |  R
:- | :- | -: | -:
c1 | a  |  1 |  1
c1 | b  |  2 |  2
c1 | a  |  3 |  3
c2 | a  |  1 |  1
c2 | a  |  2 |  1
c2 | b  |  3 |  2

如果您想要(稀疏)等级,则可以获取先前的输出并对其应用RANK分析函数:

SELECT a,RANK() OVER ( PARTITION BY a ORDER BY r ) AS r
FROM   (
  SELECT a,SUM( has_changed ) OVER ( PARTITION BY a ORDER BY c ) AS r
  FROM   (
    SELECT t.*,CASE
           WHEN b = LAG( b ) OVER ( PARTITION BY a ORDER BY c )
           THEN 0
           ELSE 1
           END AS has_changed
    FROM   table_name t
  )
)
ORDER BY a,c;

哪个输出:

A  | B  |  C |  R
:- | :- | -: | -:
c1 | a  |  1 |  1
c1 | b  |  2 |  2
c1 | a  |  3 |  3
c2 | a  |  1 |  1
c2 | a  |  2 |  1
c2 | b  |  3 |  3

您还可以使用MATCH_RECOGNIZE比较连续的行:

SELECT a,dense_rank,RANK() OVER( PARTITION BY a ORDER BY dense_rank ) AS sparse_rank
FROM   table_name
MATCH_RECOGNIZE (
   PARTITION BY a
   ORDER BY     c
   MEASURES     MATCH_NUMBER() AS dense_rank
   ALL ROWS PER MATCH
   PATTERN      (FIRST_ROW EQUAL_ROWS*)
   DEFINE       EQUAL_ROWS AS EQUAL_ROWS.b = PREV(EQUAL_ROWS.b)
)

哪个输出:

A  | B  |  C | DENSE_RANK | SPARSE_RANK
:- | :- | -: | ---------: | ----------:
c1 | a  |  1 |          1 |           1
c1 | b  |  2 |          2 |           2
c1 | a  |  3 |          3 |           3
c2 | a  |  1 |          1 |           1
c2 | a  |  2 |          1 |           1
c2 | b  |  3 |          2 |           3

db 提琴here