MySQL列具有两个列的功能,并按第三列排序

时间:2018-08-17 03:10:42

标签: mysql function rank

这是我在Sql Server中使用的代码,我想在Mysql中使用相同的代码

不幸的是,MySQL 5没有等级功能。我尝试了google仍然没有帮助按多列进行分区和按第三列进行排序

SELECT 
A.ID, A.COL1, A.COL2, A.COL3 
FROM (
SELECT
ID, COL1, COL2, COL3, ROW_NUMBER() OVER (PARTITION BY COL1, COL2 ORDER BY COL3 DESC,ID) AS RN
FROM #temp) A
WHERE A.RN=1

可以帮助它在mysql中使用

SELECT * FROM MysqlTemp
CREATE TEMPORARY TABLE MysqlTemp
(
ID INT 
, Col1 VARCHAR(20)
, Col2 VARCHAR(20)
, Col3 VARCHAR(30)
) 


INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (1,'Hi','Hi','A21');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (2,'Hi','Hi','A21');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (3,'Hello','Hello');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (4,'Hello','Hello');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (5,'Hey','Hey');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (6,'Hey','Hey','B45');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (7,'Howdy','Howdy','V44');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (8,'Howdy','Howdy');

期望值为1,3,6,7

1 个答案:

答案 0 :(得分:0)

我可以随意添加更多数据,以确保满足所有测试用例。

创建表MysqlTemp ( 编号INT ,Col1 VARCHAR(20) ,Col2 VARCHAR(20) ,Col3 VARCHAR(30) );

INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (1,'Hi','Hi','A21');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (2,'Hi','Hi','A21');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (3,'Hello','Hello');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (4,'Hello','Hello');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (5,'Hey','Hey');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (6,'Hey','Hey','B45');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (7,'Howdy','Howdy','V44');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (8,'Howdy','Howdy');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (9,'Howdy','Howdy');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (10,'Howdy','Howdy','V45');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (11,'ROWDY','ROWDY','X45');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (12,'ROWDY','ROWDY');
INSERT INTO MysqlTemp (ID,Col1,Col2) VALUES (13,'ROWDY','ROWDY');
INSERT INTO MysqlTemp (ID,Col1,Col2,Col3) VALUES (14,'ROWDY','ROWDY','X44');

    select m1.*,
(select count(1) from MysqlTemp m2 
  where   coalesce(col3,'Z') <= coalesce(m1.col3,'Z')
 and (coalesce(col3,'Z') < coalesce(m1.col3,'Z') or id <= m1.id)
 and col1 = m1.col1
 and col2 = m1.col2
   ) as rnk
from MysqlTemp m1

ID  Col1    Col2    Col3    rnk
1   Hi  Hi  A21     1
2   Hi  Hi  A21     2
3   Hello   Hello   (null)  1
4   Hello   Hello   (null)  2
5   Hey     Hey     (null)  2
6   Hey     Hey     B45     1
7   Howdy   Howdy   V44     1
8   Howdy   Howdy   (null)  3
9   Howdy   Howdy   (null)  4
10  Howdy   Howdy   V45     2
11  ROWDY   ROWDY   X45     2
12  ROWDY   ROWDY   (null)  3
13  ROWDY   ROWDY   (null)  4
14  ROWDY   ROWDY   X44     1

说明: 在mysql中,一种生成排名的方法是使用相关子查询。

对查询中的每个记录执行该部分

select count(1) from MysqlTemp m2 
      where   coalesce(col3,'Z') <= coalesce(m1.col3,'Z')
     and (coalesce(col3,'Z') < coalesce(m1.col3,'Z') or id <= m1.id)
     and col1 = m1.col1
     and col2 = m1.col2

这部分确保连接仅处理符合此条件的记录。基本上,这是分区子句。

 and col1 = m1.col1
 and col2 = m1.col2

这部分可能很简单<=,因为您有空值,可以将可达到的最大值用于比较空值。

 where   coalesce(col3,'Z') <= coalesce(m1.col3,'Z')

到目前为止,我们正在尝试计算同一分区内所有小于col3的记录。第一条记录将只有1条小于或=的记录。第二个记录的2个记录少于或=。以此类推。那才算是排名。

下面是order by子句的第二部分。

 and (coalesce(col3,'Z') < coalesce(m1.col3,'Z') or id <= m1.id)

为什么这里有额外或条件?因为id>用于第二和第三条记录,所以您将错过需要计数的第一条记录。所以一个或。

我知道那会有点模糊。分别尝试查询每个部分,您将了解。