重新查询同一个表时优化MariaDB查询

问题描述 投票:0回答:1

我正在尝试运行一个查询来获取客户上次下订单的时间。问题是该网站允许人们查看登录和注销的情况。此外,我想合并在某个时刻更改过电子邮件的客户的记录。

我有一个有效的查询(我认为),但它涉及三个选择 - 一个用于最后一个订单,一个用于登录/注销切换,一个用于电子邮件切换。这对我的数据库来说有点慢!我在忽略什么?我怎样才能使这个查询更有效和/或更快?

SELECT last, email, user_id 
FROM (
  SELECT last, email, user_id 
  FROM (
    SELECT time as last, email, 
      CASE WHEN user_id > 0 THEN CAST(user_id as CHAR(20))
      ELSE email
      END as user_id
    FROM   orders o1
    WHERE  time=(SELECT MAX(o2.time)
              FROM orders o2
              WHERE o1.email = o2.email)
    ORDER BY last DESC
  ) as o3
  GROUP BY email
) as o4
GROUP BY user_id
ORDER BY email
database mariadb
1个回答
0
投票

您可以按时间排列订单,并按复合值(user_id 或电子邮件)进行分区。
我认为有必要将 user_id 和 email 引入相同的数据类型 - 电子邮件数据类型(示例中为 varchar(50))。
参见示例:

测试数据

订单_id 用户ID 时间 电子邮件
1 100 2024-09-01 14:00:00 [电子邮件受保护]
2 100 2024-09-10 09:00:00 [电子邮件受保护]
3 200 2024-09-12 09:00:00 [电子邮件受保护]
4 300 2024-09-10 09:00:00 [电子邮件受保护]
5 300 2024-09-12 09:00:00 [电子邮件受保护]
6 400 2024-09-10 09:00:00 [电子邮件受保护]
7 400 2024-09-12 09:00:00 [电子邮件受保护]
8 400 2024-09-14 09:00:00 [电子邮件受保护]
9 0 2024-09-11 09:00:00 [电子邮件受保护]
10 0 2024-09-15 15:00:00 [电子邮件受保护]
11 0 2024-09-10 09:00:00 [电子邮件受保护]

查询示例

select *
from(
  select *
    ,row_number()over(partition by case when user_id<>0 then CAST(user_id as varCHAR(50)) else email end 
                   order by time desc) rn
  from orders
)ranged_orders
where rn=1
order by email

输出

订单_id 用户ID 时间 电子邮件 rn
2 100 2024-09-10 09:00:00 [电子邮件受保护] 1
3 200 2024-09-12 09:00:00 [电子邮件受保护] 1
5 300 2024-09-12 09:00:00 [电子邮件受保护] 1
8 400 2024-09-14 09:00:00 [电子邮件受保护] 1
10 0 2024-09-15 15:00:00 [电子邮件受保护] 1
11 0 2024-09-10 09:00:00 [电子邮件受保护] 1

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.