【问题标题】:Using MEDIAN with GROUP BY将 MEDIAN 与 GROUP BY 一起使用
【发布时间】:2018-10-31 21:49:57
【问题描述】:

从 MariaDB 10.3.3 开始,存在 MEDIAN 函数。 不幸的是,当我尝试将它与GROUP BY 语句一起使用时出现了一个小问题(目前使用的是v10.3.9)。

给定下表:

CREATE TABLE testmed
  (
     id       INT NOT NULL auto_increment,
          PRIMARY KEY(id),
     group_id INT NOT NULL DEFAULT 0,
     score    INT NOT NULL DEFAULT 0
  ); 

用一些数据填充它:

INSERT INTO testmed (group_id, score) 
VALUES (1,1), (1,2), (1,2), (1,2), (1,3), (2,5), (2,7), (2,9), (2,11), (2,11);

现在我在查询中使用和不使用GROUP BY 得到不同的结果:

MariaDB [test]> SELECT group_id, score, MEDIAN(score) OVER (PARTITION BY group_id) FROM testmed;
+----------+-------+------------------------------ --------------+
| group_id |分数 | MEDIAN(score) OVER (PARTITION BY group_id) |
+----------+-------+------------------------------ --------------+
| 1 | 1 | 2.0000000000 |
| 1 | 2 | 2.0000000000 |
| 1 | 2 | 2.0000000000 |
| 1 | 2 | 2.0000000000 |
| 1 | 3 | 2.0000000000 |
| 2 | 5 | 9.0000000000 |
| 2 | 7 | 9.0000000000 |
| 2 | 9 | 9.0000000000 |
| 2 | 11 | 9.0000000000 |
| 2 | 11 | 9.0000000000 |
+----------+-------+------------------------------ --------------+
10 行一组(0.000 秒)
MariaDB [test]> SELECT group_id, score, MEDIAN(score) OVER (PARTITION BY group_id) FROM testmed GROUP BY group_id;
+----------+-------+------------------------------ --------------+
| group_id |分数 | MEDIAN(score) OVER (PARTITION BY group_id) |
+----------+-------+------------------------------ --------------+
| 1 | 1 | 1.0000000000 |
| 2 | 5 | 5.0000000000 |
+----------+-------+------------------------------ --------------+

第一个是正确的,但为什么它不能与GROUP BY 一起正常工作。 目前我正在使用这样的查询嵌套:

MariaDB [test]> SELECT * FROM (SELECT group_id, score, MEDIAN(score) OVER (PARTITION BY group_id) FROM testmed) t GROUP BY group_id;
+----------+-------+------------------------------ --------------+
| group_id |分数 | MEDIAN(score) OVER (PARTITION BY group_id) |
+----------+-------+------------------------------ --------------+
| 1 | 1 | 2.0000000000 |
| 2 | 5 | 9.0000000000 |
+----------+-------+------------------------------ --------------+
2 行(0.000 秒)

但这样做感觉很不对。

什么是正确的做法?

【问题讨论】:

    标签: mariadb median


    【解决方案1】:

    您的第二个查询在技术上无效:

    SELECT
        group_id,
        score,
        MEDIAN(score) OVER (PARTITION BY group_id)
    FROM testmed
    GROUP BY group_id;
    

    它无效的原因是因为您选择了score,它没有出现在GROUP BY 子句中。这里的问题是score哪个 值,您打算将数据库用于每个group_id?这里似乎发生的是 MariaDB 任意选择最小值score。但由于只有一个 score 值,因此中位数只返回该单个值。

    请记住,分析函数是在发生GROUP BY 聚合之后进行评估的。我认为这是您打算运行的查询:

    SELECT DISTINCT
        group_id,
        MEDIAN(score) OVER (PARTITION BY group_id) score_median
    FROM testmed;
    

    如果这不起作用,因为 MariaDB 不喜欢将 DISTINCTMEDIAN 一起使用,那么您可以尝试子查询:

    SELECT DISTINCT
        group_id,
        score_median
    FROM
    (
        SELECT
            group_id,
            MEDIAN(score) OVER (PARTITION BY group_id) score_median
        FROM testmed
    ) t;
    

    【讨论】:

    • 您使用的是什么版本的 MariaDB?您的查询在我的 (10.3.9) 中引发了 You have an error in your SQL syntax; 错误。不幸的是,MEDIAN 似乎是仅窗口功能(不是聚合功能),这让我来这里询问其他人如何处理它的问题。
    • @DevilaN 我已经用一个查询更新了我的答案,这可能与您真正想要做的事情一致。我不知道MEDIAN 只是一个窗口函数。
    • 您的回答似乎在逻辑上与我的上一个示例相同,我觉得这样做有点偷偷摸摸。虽然谢谢你的提议。
    • @DevilaN - 我在 10.3.21 上成功了。您的确切陈述和完整的语法错误消息是什么?
    • @TimBiegeleisen - GROUP BY 明显快于 DISTINCT。 (至少在我运行的一项测试中。)
    猜你喜欢
    • 2017-10-11
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    • 2022-10-22
    相关资源
    最近更新 更多