在这个查询中,sql引擎会使用暴力以外的任何方法吗?

3okqufwl  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(231)

下面的查询检索中间值 LAT_N 价值来自 STATION 表中,通过查找 LAT_N 大于自身的值等于小于自身的值。

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 s是相等的,还是我错过了一个简单的优化机会?
(我理解此查询并非在所有情况下都提供中位数。我只是在解释了sql引擎是否会尝试将其优化到比每个子查询的暴力枚举更好的任何级别之后。

mpbci0fu

mpbci0fu1#

这不是一个“聪明”的解决方案。它很聪明,但不能完全解决问题。例如,它不适用于偶数行。
可能最安全的方法是变量:

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() 中间结果。

相关问题