You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用外层SELECT的P.game替换子查询中的EXAMPLE常量?

问题描述

我有如下查询语句:

SELECT DISTINCT P.game, 
(
SELECT AVG(dd.DUR) as median_val
FROM (
SELECT  S.val AS DUR, @rownum:=@rownum+1 as `row_number`, @total_rows:=@rownum
  FROM (SELECT TIMESTAMPDIFF(minute, M.date_start, M.date_finished) as val FROM matches M INNER JOIN tournaments T ON M.tournament_id=T.id
  WHERE M.tournament_id NOT IN (5,6) AND T.game = 'EXAMPLE'
  ORDER BY val) S, (SELECT @rownum:=0) r
) as dd
WHERE dd.row_number IN (FLOOR((@total_rows+1)/2), FLOOR((@total_rows+2)/2))
) AS duration
FROM matches M INNER JOIN tournaments P ON M.tournament_id=P.id WHERE P.id NOT IN (5,6) GROUP BY P.game

该查询可以运行,但由于T.game = 'EXAMPLE'是固定值,导致第二列的所有结果都相同。请问如何将子查询中的EXAMPLE常量替换为外层SELECT语句中的P.game值?

表结构及数据

tournaments表

CREATE TABLE tournaments (id INT PRIMARY KEY, game VARCHAR(64));
INSERT INTO tournaments (`id`, `game`) VALUES ('1', 'EXAMPLE'), ('2', 'TETRIS'), ('3', 'MARIO'), ('4', 'EXAMPLE'), ('5', 'TETRIS'), ('6', 'MARIO');

数据:

idgame
1EXAMPLE
2TETRIS
3MARIO
4EXAMPLE
5TETRIS
6MARIO

matches表

CREATE TABLE matches (id INT PRIMARY KEY, tournament_id INT, date_start DATETIME, date_finished DATETIME);
INSERT INTO matches (`id`, `tournament_id`, `date_start`, `date_finished`) VALUES ('1', '1', '2024-01-18 01:10:00', '2024-01-18 01:12:00'), ('2', '2', '2024-01-18 01:10:00', '2024-01-18 01:18:00'), ('3', '3', '2024-01-18 01:10:00', '2024-01-18 01:16:00'), ('4', '3', '2024-01-18 01:10:00', '2024-01-18 01:22:00'), ('5', '2', '2024-01-18 01:10:00', '2024-01-18 01:31:00'), ('6', '1', '2024-01-18 01:10:00', '2024-01-18 01:19:00'), ('7', '2', '2024-01-18 01:10:00', '2024-01-18 01:45:00'), ('8', '4', '2024-01-18 01:10:00', '2024-01-18 01:28:00'), ('9', '4', '2024-01-18 01:10:00', '2024-01-18 01:54:00'), ('10', '5', '2024-01-18 01:10:00', '2024-01-18 01:12:00'), ('11', '6', '2024-01-18 01:10:00', '2024-01-18 01:18:00'), ('12', '7', '2024-01-18 01:10:00', '2024-01-18 01:16:00'), ('13', '7', '2024-01-18 01:10:00', '2024-01-18 01:22:00'), ('14', '6', '2024-01-18 01:10:00', '2024-01-18 01:31:00'), ('15', '5', '2024-01-18 01:10:00', '2024-01-18 01:19:00'), ('16', '6', '2024-01-18 01:10:00', '2024-01-18 01:45:00'), ('17', '6', '2024-01-18 01:10:00', '2024-01-18 01:28:00'), ('18', '5', '2024-01-18 01:10:00', '2024-01-18 01:54:00');

数据:

idtournament_iddate_startdate_finished
112024-01-18 01:10:002024-01-18 01:12:00
222024-01-18 01:10:002024-01-18 01:18:00
332024-01-18 01:10:002024-01-18 01:16:00
432024-01-18 01:10:002024-01-18 01:22:00
522024-01-18 01:10:002024-01-18 01:31:00
612024-01-18 01:10:002024-01-18 01:19:00
722024-01-18 01:10:002024-01-18 01:45:00
842024-01-18 01:10:002024-01-18 01:28:00
942024-01-18 01:10:002024-01-18 01:54:00
1052024-01-18 01:10:002024-01-18 01:12:00
1162024-01-18 01:10:002024-01-18 01:18:00
1272024-01-18 01:10:002024-01-18 01:16:00
1372024-01-18 01:10:002024-01-18 01:22:00
1462024-01-18 01:10:002024-01-18 01:31:00
1552024-01-18 01:10:002024-01-18 01:19:00
1662024-01-18 01:10:002024-01-18 01:45:00
1762024-01-18 01:10:002024-01-18 01:28:00
1852024-01-18 01:10:002024-01-18 01:54:00

期望结果

按game分组,第二列为对应game的比赛时长中位数(TIMESTAMPDIFF(minute, M.date_start, M.date_finished)的中位数):

gameduration
EXAMPLE13.5
TETRIS21
MARIO9
解决方案

要让子查询引用外层的P.game,需将子查询改为关联子查询,同时确保每个分组的行号变量重新初始化,修改后的查询语句如下:

SELECT 
    P.game,
    (
        SELECT AVG(dd.DUR) AS median_val
        FROM (
            SELECT 
                S.val AS DUR,
                @rownum := @rownum + 1 AS `row_number`,
                @total_rows := @rownum
            FROM (
                SELECT TIMESTAMPDIFF(minute, M.date_start, M.date_finished) AS val
                FROM matches M
                INNER JOIN tournaments T ON M.tournament_id = T.id
                WHERE M.tournament_id NOT IN (5,6) 
                  AND T.game = P.game  -- 替换为外层的P.game
                ORDER BY val
            ) S,
            (SELECT @rownum := 0) r  -- 每个分组重新初始化行号变量
        ) dd
        WHERE dd.row_number IN (FLOOR((@total_rows + 1)/2), FLOOR((@total_rows + 2)/2))
    ) AS duration
FROM matches M
INNER JOIN tournaments P ON M.tournament_id = P.id
WHERE P.id NOT IN (5,6)
GROUP BY P.game;

关键说明

  1. 将子查询中的T.game = 'EXAMPLE'替换为T.game = P.game,使子查询随外层分组的game值筛选对应数据。
  2. 每个子查询执行时通过(SELECT @rownum := 0) r重新初始化行号变量,避免不同分组的行号混乱。
  3. 原查询中的DISTINCT可删除,GROUP BY P.game已保证game的唯一性。

执行该查询后,即可得到每个game对应的比赛时长中位数,与期望结果一致。


内容的提问来源于stack exchange,提问作者artyn1989

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:50:57