下面的查询通过查找LAT_N
值大于其自身的数量等于小于其自身的值的记录,从STATION
表中检索LAT_N
的中值。 / p>
SELECT ROUND(S.LAT_N, 4) AS MEDIAN FROM STATION S WHERE
(SELECT COUNT(LAT_N) FROM STATION WHERE LAT_N < S.LAT_N) =
(SELECT COUNT(LAT_N) FROM STATION WHERE LAT_N > S.LAT_N)
这是一个聪明的解决方案,其他人将其发布为Hackerrank问题的解决方案,但我想知道SQL引擎将如何解决这个问题。
这种不寻常的查询结构是否只需要对两个子查询进行强行强制,直到它们的COUNT
相等,或者缺少一个容易实现的优化机会?
(我知道此查询不会在任何情况下都提供中位数。我只是在说明SQL引擎是否会尝试将其优化到比每个子查询的蛮力枚举更好的水平)
答案 0 :(得分:0)
这不是“智能”解决方案。它很聪明,但是并不能完全解决问题。例如,它对于偶数行不起作用。
最安全的方法可能是变量:
SELECT ROUND(AVG(S.LAT_N), 4) AS MEDIAN
FROM (SELECT S.*, (@rn := @rn + 1) as seqnum
FROM (SELECT S.* FROM STATION S ORDER BY S.LAT_N) S CROSS JOIN
(SELECT @rn := 0) params
) S
WHERE 2 * seqnum IN (@rn, @rn + 1, @rn + 2) ;
无论行数或值的分布如何,此方法都应起作用。还有一种使用GROUP_CONCAT()
的聪明方法,但其实用程序限于GROUP_CONCAT()
中间结果的最大长度。