在刚刚结束的“SQL 挑战赛第三期”中,众多 SQL 爱好者积极参与,展现了他们在数据处理、逻辑思维和创新方面的优秀能力。除了 Oracle、PostgreSQL 等国外主流数据库以外,我们还看到有不少的参赛者使用如 OceanBase、openGauss、GreatDB 等国产数据库,这不仅体现了 SQL 技术的广泛应用,也展示了国内数据库技术的蓬勃发展和社区的多样性。
经过认真的评审,我们已经完成了对参赛作品的评估。现在,让我们来看看本期 SQL 挑战赛的奖项评比结果。
第一名:老虎刘
作品展示
使用Oracle数据库
oracle 12c+ 版本,可以用最简洁的语句实现:
select *
from user_actions
match_recognize
(partition by user_id
order by action_time
Measures
match_number() as session_id,
first(action_time) as begin_time,
last(action_time) as end_time
one row per match
pattern (strt in30*)
define in30 as (action_time<=prev(action_time)+30/60/24)
);
点评:
代码逻辑清晰,结构简洁,利用 MATCH_RECOGNIZE 有效实现了会话分割,既保证了结果的准确性,也体现了良好的实现思路和表达方式。
第二名:锁钥
作品展示
使用PostgreSQL数据库
-- PostgreSQL数据库
-- 构造测试数据
create table user_actions (user_id int,action_time timestamp);
INSERT INTO user_actions VALUES
(1, '2025-05-01 08:00:00'),
(1, '2025-05-01 08:15:00'),
(1, '2025-05-01 09:00:00'), -- 间隔超过30分钟,新会话
(2, '2025-05-01 10:00:00');
-- CTE
WITH temp_bd AS (
SELECT
user_id,
action_time,
-- 先获取间隔超过30分钟的分组条件
CASE
WHEN EXTRACT(EPOCH FROM (action_time - LAG(action_time) OVER (PARTITION BY user_id ORDER BY action_time))) > 1800
OR LAG(action_time) OVER (PARTITION BY user_id ORDER BY action_time) IS NULL
THEN 1
ELSE 0
END AS new_session
FROM user_actions
),
temp_gp AS (
SELECT
user_id,
action_time,
-- 再聚合user_id
SUM(new_session) OVER (PARTITION BY user_id ORDER BY action_time) AS session_id
FROM temp_bd
)
SELECT
user_id,
session_id,
-- 提取分组会话起始时间区间
MIN(action_time) AS start_time,
MAX(action_time) AS end_time
FROM temp_gp
GROUP BY user_id, session_id
ORDER BY user_id, session_id;
点评:
代码逻辑严谨,结构清晰,通过 LAG 和 SUM 等窗口函数识别新会话边界,并结合分组聚合提取起止时间,整体实现思路明确,表达方式较为优雅。
第三名:沐炎
作品展示
使用MySQL数据库
作品展示:
数据库:MySQL8.0
建表语句:CREATE TABLE user_actions (user_id INT,action_time DATETIME);
插入示例数据:
INSERT INTO user_actions VALUES
(1, '2025-05-01 08:00:00'),
(1, '2025-05-01 08:15:00'),
(1, '2025-05-01 09:00:00'), -- 间隔超过30分钟,新会话
(2, '2025-05-01 10:00:00');
编写的SQL语句:
WITH ordered_actions AS (
SELECT
user_id,
action_time,
LAG(action_time) OVER (PARTITION BY user_id ORDER BY action_time) AS prev_time
FROM user_actions
),
session_flags AS (
SELECT
user_id,
action_time,
CASE
WHEN prev_time IS NULL OR TIMESTAMPDIFF(SECOND, prev_time, action_time) > 1800 THEN 1
ELSE 0
END AS is_new_session
FROM ordered_actions
),
session_numbers AS (
SELECT
user_id,
action_time,
SUM(is_new_session) OVER (PARTITION BY user_id ORDER BY action_time) AS session_id
FROM session_flags
),
session_ranges AS (
SELECT
user_id,
session_id,
MIN(action_time) AS start_time,
MAX(action_time) AS end_time
FROM session_numbers
GROUP BY user_id, session_id
)
SELECT
user_id,
session_id,
start_time,
end_time
FROM session_ranges
ORDER BY user_id, session_id;
点评:
代码逻辑正确,结构清晰,使用了LAG和SUM窗口函数来标记新会话,并通过GROUP BY聚合会话的开始时间和结束时间。
合格奖
| 范计杰 | 小草 | 蝎的沿途 | 六月暴雪飞梨花 |
|---|---|---|---|
| 周波 | Alex | 听见风的声音 | 智慧小匠人 |
| 披头 | 刘晨 | qabel12 | 孙莹 |
【优秀作品奖】:墨天轮新周边一套(运动水壶+T恤+鼠标垫)
【合格参赛奖】:100墨值
- 请获得优秀奖的朋友联系小墨(modb666),并通过私信告知邮寄方式。
- 对于获得合格奖的朋友,我们将在5月16日12点之前将墨汁发放至您的账户,请注意查收。
再次祝贺所有获奖者,也感谢每一位参赛者的付出!希望未来能有更多这样的活动,让大家有机会展示自己的才能,共同推动 SQL 技术的发展。期待下次比赛再见!
最后修改时间:2025-05-15 18:17:43
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




