【问题标题】:how can i write rank sql in oracle like mysql我怎样才能像mysql一样在oracle中编写rank sql
【发布时间】:2021-01-09 10:49:54
【问题描述】:

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

【问题讨论】:

  • 为什么c1 值的排名是 1、2、3?您有两个 a 值;那些不应该有相同的排名吗?
  • 我只是想比较相邻的行,我不在乎有多少'a'
  • @user8694776 (a,b,a) 列表看起来不像“相邻”或排序。没有订单
  • 行无序。因此,如果您想比较相邻的行,则需要另一列来对结果进行排序。
  • 详细了解 Oracle 中的分析函数 rank/dense_rank:oracle-base.com/articles/misc/…

标签: mysql oracle rank


【解决方案1】:

使用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', 'a' FROM DUAL UNION ALL
SELECT 'c2', 'a' FROM DUAL UNION ALL
SELECT 'c2', 'b' FROM DUAL;

这个输出:

一个 |乙| R :- | :- | -: c1 |一个 | 1 c1 |一个 | 1 c1 |乙 | 3 c2 |一个 | 1 c2 |一个 | 1 c2 |乙 | 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', 'a', 3 FROM DUAL UNION ALL
SELECT 'c2', 'a', 1 FROM DUAL UNION ALL
SELECT 'c2', 'a', 2 FROM DUAL UNION ALL
SELECT 'c2', 'b', 3 FROM DUAL;

这将找到行的密集等级:

SELECT a,
       b,
       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;

哪些输出:

一个 |乙| C | R :- | :- | -: | -: c1 |一个 | 1 | 1 c1 |乙 | 2 | 2 c1 |一个 | 3 | 3 c2 |一个 | 1 | 1 c2 |一个 | 2 | 1 c2 |乙 | 3 | 2

如果您想要(稀疏)排名,那么您可以获取先前的输出并将RANK 分析函数应用于它:

SELECT a,
       b,
       c,
       RANK() OVER ( PARTITION BY a ORDER BY r ) AS r
FROM   (
  SELECT a,
         b,
         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;

哪些输出:

一个 |乙| C | R :- | :- | -: | -: c1 |一个 | 1 | 1 c1 |乙 | 2 | 2 c1 |一个 | 3 | 3 c2 |一个 | 1 | 1 c2 |一个 | 2 | 1 c2 |乙 | 3 | 3

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

SELECT a,
       b,
       c,
       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)
)

哪些输出:

一个 |乙| C | DENSE_RANK | SPARSE_RANK :- | :- | -: | ---------: | ----------: c1 |一个 | 1 | 1 | 1 c1 |乙 | 2 | 2 | 2 c1 |一个 | 3 | 3 | 3 c2 |一个 | 1 | 1 | 1 c2 |一个 | 2 | 1 | 1 c2 |乙 | 3 | 2 | 3

db小提琴here

【讨论】:

  • 喝点茶,大师!它给了我一个新的想法,虽然我的 Oracle 是 11。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多