【问题标题】:5th percentile on MySQL (MariaDB)MySQL (MariaDB) 上的第 5 个百分位
【发布时间】:2020-01-25 00:51:35
【问题描述】:

我正在尝试使用 ~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 这个查询吗?甚至可以改进原来的方法?

提前谢谢你,

TheJazzle

附言。这是我的数据库的链接,如果您想弄乱/测试它:https://gofile.io/?c=Ga6ODr

【问题讨论】:

    标签: mysql sql mariadb mariadb-10.2


    【解决方案1】:

    此查询应为您提供所需的结果。它通过price 分配ROW_NUMBER 并计算CTE 中每个type_id 和订单类型(is_buy_order)的所有行,然后选择MAX 价格作为buy 价格(对于@987654330 @),并且行的最低价格 >= 第 95 个百分位作为第 95 个百分位价格。如果第 95 个百分位数中除最高价格外没有任何行,则返回第二高价格。类似的逻辑适用于sell95th%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

    【讨论】:

    • 评论不用于扩展讨论;这个对话是moved to chat
    • @SamuelLiew OP 没有足够的代表来进行聊天。但是感谢您的清理,它有点乱......
    • 嗨尼克,对于卖出,它应该加载第二低的值(在本例中为 2.03),但它选择了最低值(与 MIN(sell) 相同)(imgur.com/a/NRmBQpN)跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 2023-02-24
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 2012-10-31
    相关资源
    最近更新 更多