更改 sql 以摆脱窗口函数

Posted

技术标签:

【中文标题】更改 sql 以摆脱窗口函数【英文标题】:Changing sql to get rid of windowed functions 【发布时间】:2020-10-01 10:24:11 【问题描述】:

我正在尝试在远程 mysql 数据库上创建视图,不幸的是,安装的版本 (5.7) 似乎不支持窗口功能。一切都在我的本地数据库上运行,但现在我有点卡住了。

这是之前的代码:

create or replace view my_view as 
( 
with a as 
    (select a.*, DENSE_RANK() over (partition by SHOP order by TIMESTAMP(LOAD_TIME) DESC) rn 
     from my_table as a) 
select row_number() OVER () as id, SHOP, LOAD_TIME from a WHERE a.rn = 1
);

Mysql 5.7 也不支持 CTE,不过问题不大。

任何提示如何解决这个问题?

【问题讨论】:

你能提供样本数据和想要的结果吗? 【参考方案1】:

更换dense_rank() 非常简单。但是,替换row_number() 更加困难。 MySQL 不允许视图中的变量。不幸的是,这也使您对行号的子查询效率低下:

select (select count(distinct shop)
        from mytable t2
        where t2.shop <= t.shop
       ) as id,
       shop, load_time
from mytable t
where t.load_time = (select max(t2.load_time) from mytable t2 where t2.shop = t.shop);

或者,如果您只有这两列,请使用聚合:

select (select count(distinct shop)
        from mytable t2
        where t2.shop <= t.shop
       ) as id,
       shop, max(load_time) as load_time
from mytable t
group by shop;

这不是有效的。在一个简单的查询中,您可以使用变量:

select (@rn := @rn + 1) as id,
       shop, load_time
from mytable t cross join
     (select @rn := 0) params
where t.load_time = (select max(t1.load_time) from mytable t1 where t1.shop = t.shop);

如果性能是一个问题,那么您可能希望创建一个表而不是视图,并使用触发器使其保持最新状态。

【讨论】:

【参考方案2】:

您可以使用相关子查询处理过滤部分:

create or replace view my_view as 
select shop, load_time
from mytable t
where t.load_time = (select max(t1.load_time) from mytable t1 where t1.shop = t.shop)

【讨论】:

以上是关于更改 sql 以摆脱窗口函数的主要内容,如果未能解决你的问题,请参考以下文章

如何通过窗口函数过滤聚合函数的 SQL 语句中的行?

查找逾期天数的 SQL 窗口函数

Hive sql及窗口函数

SQL 窗口函数 - SELECT DISTINCT ORDER BY LIMIT

重学SQL窗口函数

SQL窗口函数