微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SELECT 子句中的 SQL 子查询

如何解决SELECT 子句中的 SQL 子查询

我正在尝试查找过去 30 天内的管理员活动。

accounts 表存储了用户数据(用户名、密码等)

在每天结束时,如果用户登录,它将在 player_history 表中创建一个新条目,其中包含更新的数据。这样我们就可以随着时间的推移跟踪进度。

帐户表:

id 用户名 管理员
1 迈克尔 4
2 史蒂夫 3
3 露易丝 3
4 0
5 艾米 1

player_history 表:

id user_id created_at 游戏时间
0 1 2021-04-03 10
1 2 2021-04-04 10
2 3 2021-04-05 15
3 4 2021-04-10 20
4 5 2021-04-11 20
5 1 2021-05-12 40
6 2 2021-05-13 55
7 3 2021-05-17 65
8 4 2021-05-19 75
9 5 2021-05-23 30
10 1 2021-06-01 60
11 2 2021-06-02 65
12 3 2021-06-02 67
13 4 2021-06-03 90

以下查询

SELECT a.`username`,SEC_TO_TIME((MAX(h.`playtime`) - MIN(h.`playtime`))*60) as 'time' FROM `player_history` h,`accounts` a WHERE h.`created_at` > '2021-05-06' AND h.`user_id` = a.`id` AND a.`admin` > 0 GROUP BY h.`user_id`

输出这个表:

请注意,这只是管理员活动,因此此数据中不包含 Joe。

从 2021-05-06 到现在(yy-mm-dd):

用户名 时间
迈克尔 00:20:00
史蒂夫 00:10:00
露易丝 00:02:00
艾米 00:00:00

正如您从数据中看到的那样,虽然艾米在上个月玩了 10 分钟,但她的时间显示为 0。这是因为她从 2021-05-06 开始只有 1 个条目,因此没有可比较的数据。它是 0,因为 10-10 = 0。

一个缺陷是它没有包括上个月的所有活动,基本上只是从最低值中减去最高值。

因此,我尝试通过将 2021 年 5 月 6 日之后的最高值与该日期之前的最近一次登录进行比较来解决此问题。所以我稍微修改查询

SELECT a.`Username`,SEC_TO_TIME((MAX(h.`playtime`) - (SELECT MAX(`playtime`) FROM `player_history` WHERE a.`id` = `user_id` AND `created_at` < '2021-05-06'))*60) as 'Time' FROM `player_history` h,`accounts` a WHERE h.`created_at` >= '2021-05-06' AND h.`user_id` = a.`id` AND a.`admin` > 0 GROUP BY h.`user_id`

所以现在它会输出

用户名 时间
迈克尔 00:50:00
史蒂夫 00:50:00
露易丝 00:52:00
艾米 00:10:00

但我觉得整个查询效率很低。有没有更好的方法来做到这一点?

解决方法

我想你想要lag()

SELECT a.username,SEC_TO_TIME(SUM(h.playtime - COALESCE(h.prev_playtime,0))) as time
FROM accounts a JOIN
     (SELECT h.*,LAG(playtime) OVER (PARTITION BY u.user_id ORDER BY h.created_at) as prev_playtime
      FROM player_history h
     ) h
     ON h.user_id = a.id
WHERE h.created_at > '2021-05-06' AND
      a.admin > 0
GROUP BY a.username;

除了 LAG() 逻辑之外,请注意查询的其他更改:

  • 使用正确、明确、标准、可读的 JOIN 语法。
  • SELECTGROUP BY 使用一致的列。
  • 删除列别名周围的单引号。
  • 去除反引号;它们只会使查询变得混乱,使编写和阅读变得更加困难。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。