【问题标题】:convert rank() over (partition .... in mysql 5.7 [duplicate]在 mysql 5.7 中将 rank() 转换为 (partition ....) [重复]
【发布时间】:2020-08-01 08:17:21
【问题描述】:

我正在尝试在 mysql 5.7 中转换以下 sql

 SELECT T.STOREID AS STOREID,
           T.ARTID AS ARTID,
           T.TOTAMOUNT,
           MAX(T.HOUR) AS HOUR,
           RANK() OVER (PARTITION BY T.STOREID, T.ARTID
                        ORDER BY T.STOREID, T.ARTID, T.HOUR DESC) AS RN
    FROM T
ORDER BY T.STOREID,
         T.ARTID

这在 oracle 中运行完美,但在 mysql 中确实有效,因为只有 mysql 8 及更高版本支持这一点。谁能帮我在 mysql 5.7 中获得相同的结果

【问题讨论】:

  • 也许升级??
  • 我认为 MySQL 5.7 中没有针对它的 SQL 解决方案。您需要以有序的方式检索行并在应用程序中对数据进行后处理以计算排名。这不仅仅是ROW_NUMBER(),我认为相关答案并没有解决您的问题。

标签: mysql sql select subquery window-functions


【解决方案1】:

首先,关于您的原始查询的几点说明:

  • 它不是有效的 SQL; select 子句 (max(t.hour)) 中有聚合函数,但没有 group by 子句

  • rank()order by 子句未优化:它从属于partition by 子句的列开始,这是不必要的(我们已经知道分区中的所有行都具有相同的值对于这些列)

所以我假设你要重写的查询是:

select 
    t.storeid as storeid,
    t.artid as artid,
    t.totamount,
    t.hour,
    rank() over(partition by t.storeid, t.artid order by t.hour desc) rn
from t
order by t.storeid, t.artid

现在,在 MySQL 5.7 中,一种模拟 rank() 的方法使用相关子查询:

select 
    t.storeid as storeid,
    t.artid as artid,
    t.totamount,
    t.hour,
    (
        select 1 + count(*)
        from t t1
        where 
            t1.storeid = t.storeid 
            and t1.artid = t.artid
            and t1.hour > t.hour

    ) as rn
from t
order by t.storeid, t.artid

请注意,这确实比窗口函数效率低,因为必须为原始表中的每一行执行子查询。其他解决方案通常涉及用户变量。

【讨论】:

    猜你喜欢
    • 2018-04-02
    • 2016-05-14
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多