AWS Athena:不支持的相关子查询类型,但它适用于 Mysql 和其他风格
Posted
技术标签:
【中文标题】AWS Athena:不支持的相关子查询类型,但它适用于 Mysql 和其他风格【英文标题】:AWS Athena: Unsupported correlated subquery type but it works on Mysql and other flavors 【发布时间】:2020-10-30 20:02:49 【问题描述】:对于订单表中的每个订单,我都在尝试根据 time_sent 返回最新的订单更新值,并分组为一行。
CREATE TABLE order_updates (time_sent INTEGER, order_id INTEGER, a VARCHAR(2), b VARCHAR(2), c VARCHAR(2), d VARCHAR(2));
INSERT INTO order_updates (time_sent, order_id, a, b, c, d) VALUES
('1', '1', 'a1', null, null, null),
('2', '1', null, 'b1', null, null),
('3', '1', null, null, 'c0', null),
('4', '1', 'a3', null, 'c3', null),
('5', '1', 'a0', null, null, null),
('6', '2', 'a3', 'b0', null, 'd2'),
('7', '2', null, 'b3', null, null);
CREATE TABLE orders (order_id INTEGER, name VARCHAR(32));
insert into orders (order_id, name) values (1, "joe"), (2, "bill");
select *, (select order_updates.a from order_updates where order_updates.order_id = orders.order_id and order_updates.a is not null order by order_updates.time_sent desc limit 1) a,
(select order_updates.b from order_updates where order_updates.order_id = orders.order_id and order_updates.b is not null order by order_updates.time_sent desc limit 1) b,
(select order_updates.c from order_updates where order_updates.order_id = orders.order_id and order_updates.c is not null order by order_updates.time_sent desc limit 1) c,
(select order_updates.d from order_updates where order_updates.order_id = orders.order_id and order_updates.d is not null order by order_updates.time_sent desc limit 1) d
FROM orders;
上述选择查询在 mysql 中可以正常工作,但在 AWS Athena 中却不行。
下面的工作 MySQL 示例:
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=66f17cf9f3c8f19f758c7cb1381d8207
有没有办法使用连接来完成上述操作?
【问题讨论】:
只使用连接?如果不支持相关子查询,则根本无法使用它们。并非所有数据库都支持相同的功能。 有没有办法使用连接来完成上述操作?你能举个例子吗? FWIW 您的查询在最新的 Presto (345) 中按原样工作。 做左连接,以防万一...... 【参考方案1】:可以使用窗口函数来实现这一点 - 如Athena/Presto 0.172 中提供的,这里是获取列 a 和 b 的示例,可扩展为 c 和 d:
with order_updates_a as
(
select order_id,a
,ROW_NUMBER()OVER(partition by order_id order by time_sent desc) nr
from order_updates
where a <> '' and a is not null
)
,order_updates_b as
(
select order_id,b
,ROW_NUMBER()OVER(partition by order_id order by time_sent desc) nr
from order_updates
where b <> '' and b is not null
)
,order_updates_c as
(
select order_id,c
,ROW_NUMBER()OVER(partition by order_id order by time_sent desc) nr
from order_updates
where c <> '' and c is not null
)
,order_updates_d as
(
select order_id,d
,ROW_NUMBER()OVER(partition by order_id order by time_sent desc) nr
from order_updates
where d <> '' and d is not null
)
select o.*
,a.a
,b.b
,c.c
,d.d
from order o
left join order_updates_a a
on o.order_id = a.order_id and a.nr = 1
left join order_updates_b b
on o.order_id = b.order_id and b.nr = 1
left join order_updates_c c
on o.order_id = c.order_id and c.nr = 1
left join order_updates_d d
on o.order_id = d.order_id and d.nr = 1
【讨论】:
谢谢,这适用于 a 列,但不适用于 c 列,因为 c 列的最后一行没有任何内容。目标是如果每列在某个时间点有值,则返回其最新的非空值。 这是一个例子——你可以为 c 和 d 扩展它。 patten 类似于 b 部分。 添加了c和d部分,据说和b完全一样。 问题在于,对于列 c 和 d,下面的 select 语句在第 1 行 (nr=1) 中返回空值,因为这些列在按 time_sent 排序时作为最新行具有空值: SELECT order_id, c, ROW_NUMBER() OVER(partition by order_id ORDER BY time_sent desc) nr FROM order_updates WHERE c is NOT NULL 好的,我通过添加一个 '' 来让它工作,并且,在上面的选择语句中,我更新了你提供的解决方案。再次感谢您的帮助。以上是关于AWS Athena:不支持的相关子查询类型,但它适用于 Mysql 和其他风格的主要内容,如果未能解决你的问题,请参考以下文章
AWS Athena 并发限制:提交的查询数 VS 正在运行的查询数