mysql - MySQL (MariaDB) 上的第五个百分位

标签 mysql sql mariadb mariadb-10.2

我正在尝试使用大约 300k 行表中的订单来查找商品价格的第 95 个百分位数(以及最高购买量)。

我已经成功地使用以下代码找到了第 95 个百分位数和单个商品的最高购买量:

 SELECT type_id,
       Max(price) AS buy,
       Min(price) AS '95th% buy'
FROM   (SELECT *,
               ( Row_number()
                   OVER (
                     partition BY type_id
                     ORDER BY price DESC) ) AS rownr
        FROM   orderbuffertest AS rownr
        WHERE  is_buy_order = 1
        ORDER  BY ( Row_number()
                      OVER (
                        partition BY type_id
                        ORDER BY price DESC) ) ASC) AS t1
WHERE  t1.type_id = 44992
       AND t1.rownr < (SELECT Count(*)
                       FROM   orderbuffertest
                       WHERE  is_buy_order = 1
                              AND type_id = 44992) * 0.05;  

但是,现在我尝试GROUP BY type_id,但它弄乱了我的所有值。

有人知道如何GROUP BY type_id此查询吗?也许甚至可以改进原始方法?

提前谢谢你,

TheJozzle

诗。这是我的数据库的链接,如果您想使用它进行困惑/测试:https://gofile.io/?c=Ga6ODr

最佳答案

这个查询应该会给你你想要的结果。它按 price 分配一个 ROW_NUMBER,并计算每个 type_id 和订单类型 (is_buy_order) 的所有行数CTE,然后选择 MAX 价格作为 购买 价格(对于 is_buy_order = 1),以及 >= 第 95 行的最低价格百分位作为第 95 个百分位价格。如果第 95 个百分位数中除了最高价格之外没有任何行,则返回第二高价格。类似的逻辑适用于卖出95%sell价格的生成:

WITH prices AS (
  SELECT type_id, price, is_buy_order,
         ROW_NUMBER() OVER (PARTITION BY type_id, is_buy_order ORDER BY price DESC) AS rownr,
         COUNT(*) OVER (PARTITION BY type_id, is_buy_order) AS num_rows
  FROM   orderbuffertest
)
SELECT type_id,
       MAX(CASE WHEN is_buy_order = 1 THEN price END) AS buy,
       COALESCE(MIN(CASE WHEN is_buy_order = 1 AND 100.0 * (rownr - 1) / num_rows <= 5 AND rownr != 1 THEN price END), 
                MAX(CASE WHEN is_buy_order = 1 AND rownr = 2 THEN price END)) AS `95th%buy`,
       MIN(CASE WHEN is_buy_order = 0 THEN price END) AS sell,
       COALESCE(MAX(CASE WHEN is_buy_order = 0 AND 100.0 * rownr / num_rows >= 95 AND rownr != num_rows THEN price END), 
                MAX(CASE WHEN is_buy_order = 0 AND rownr = num_rows - 1 THEN price END)) AS `95th%sell`
FROM prices
GROUP BY type_id

如果由于某种原因无法使用 CTE,您可以将 CTE 编写为子查询:

SELECT type_id,
       MAX(CASE WHEN is_buy_order = 1 THEN price END) AS buy,
       COALESCE(MIN(CASE WHEN is_buy_order = 1 AND 100.0 * (rownr - 1) / num_rows <= 5 AND rownr != 1 THEN price END), 
                MAX(CASE WHEN is_buy_order = 1 AND rownr = 2 THEN price END)) AS `95th%buy`,
       MIN(CASE WHEN is_buy_order = 0 THEN price END) AS sell,
       COALESCE(MAX(CASE WHEN is_buy_order = 0 AND 100.0 * rownr / num_rows >= 95 AND rownr != num_rows THEN price END), 
                MAX(CASE WHEN is_buy_order = 0 AND rownr = num_rows - 1 THEN price END)) AS `95th%sell`
FROM (
  SELECT type_id, price, is_buy_order,
         ROW_NUMBER() OVER (PARTITION BY type_id, is_buy_order ORDER BY price DESC) AS rownr,
         COUNT(*) OVER (PARTITION BY type_id, is_buy_order) AS num_rows
  FROM   orderbuffertest
) prices
GROUP BY type_id

Demo on dbfiddle

关于mysql - MySQL (MariaDB) 上的第五个百分位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59905423/

相关文章:

Mysql从同一表中的同一行返回多列

android - 如何使用 Greendao 执行以下查询?

performance - Maria DB INDEX 选择 - 为什么 maria 选择次优索引?

mysql - 从 InnoDB 表中删除并重用第一个自动增量 ID

html - 让 PHP 和 SQL 脚本正常工作

mysql 全文搜索任何字符串

mysql - SSRS : Using temp tables in the SSRS report query

mysql - Magento 中哪个表保存主图像的信息

MySQL如何GROUP_CONCAT特定字段?

php - 调用 mysqli 查询后如何过滤字段中的数据。