【问题标题】:MySQL - Limit by bottom (X) percent of rowsMySQL - 行的底部(X)百分比限制
【发布时间】:2014-07-15 17:14:45
【问题描述】:

这是我的表结构:

+-------+--------+----------+
| item  | price  | quantity |
+-------+--------+----------+
| 22452 | 579150 |        4 |
| 34664 | 334425 |        7 |
| 32249 | 204750 |        3 |
| 39970 |  97500 |        5 |
| 36907 | 116415 |        6 |
|  4338 | 207451 |       17 |
| 23425 | 388050 |        4 |
| 23427 | 532350 |       14 |
| 76080 | 180000 |        6 |
| 76076 | 400000 |        4 |
+-------+--------+----------+

项目不是唯一的,每个项目可能有 1 到几千行不等,因此我按项目对结果进行分组。我当前的查询如下:

SELECT  item AS id,
        COUNT(item) as total,
        ROUND(AVG(price/quantity)) AS mean,
        ROUND(MIN(price/quantity)) AS cheapest
FROM `data`
GROUP BY item;

除了这 4 个结果之外,我还想计算 (price/quantity) 值的底部 15% 行的平均价格(不是

下面的答案更新

使用下面的@GordonLinoff 答案让我基本上一路走来。但是,我确实遇到了两个问题。最大的一个是 @rn 变量没有重置,这导致它保持递增,随后只有第一行项目被包含在内。第二个是在表中出现次数的 15%

SELECT item AS id,
       COUNT(item) as total,
       ROUND(AVG(price/quantity)) AS mean,
       ROUND(MIN(price/quantity)) AS cheapest,
       ROUND(avg(case when rn <= IF(cnt * 0.15 < 1, cnt, cnt * 0.15) then price/quantity end)) as Cheapest15Percent 
FROM
    (SELECT d.*, cnt, IF(@item = d.item, @rn := @rn + 1, if(@item := d.item, @rn := 1, 1)) as rn
    FROM `data` d LEFT JOIN
        (SELECT item, COUNT(*) cnt FROM `udata` GROUP BY item) di
    ON d.item = di.item CROSS JOIN
       (SELECT @rn := 0, @item := -1) vars
    ORDER BY d.item, d.price/d.quantity) d
GROUP BY d.item;

【问题讨论】:

  • 如果您愿意,请考虑遵循以下简单的两步操作: 1. 如果您还没有这样做(您还没有这样做),请提供适当的 DDL(和/或 sqlfiddle),以便我们可以更容易地复制问题。 2. 如果您尚未这样做,请提供与步骤 1 中提供的信息相对应的所需结果集。
  • 您想要每件商品吗?还是聚合后的表?
  • @GordonLinoff 每个项目。我想获得项目出现在“数据”中的次数。如果项目 1234 出现 100 次,我想按(价格/数量)ASC 对该项目进行排序,然后获得前 15 行(100*0.15)的(价格/数量)的平均值。

标签: mysql sql sql-limit


【解决方案1】:

这假设您想要每件商品的平均 15% 最便宜。

以下查询枚举每个项目的行并获取总行数:

  select d.*, cnt,
         if(@item = item, @rn := @rn + 1, if(@item := item, 1, 1)) as rn
  from `data` d left join
       (select item, count(*) cnt
        from data
        group by item
       ) di
       on d.item = di.item cross join
       (select @rn := 0, @item := -1) vars
  order by item, price/quantity;

然后您基本上可以将其插入到您的查询中并进行条件聚合:

SELECT item AS id,
       COUNT(item) as total,
       ROUND(AVG(price/quantity)) AS mean,
       ROUND(MIN(price/quantity)) AS cheapest,
       avg(case when rn <= cnt * 0.15 then price/quantity end) as Cheapest15Percent
FROM (select d.*, cnt,
             if(@item = item, @rn := @rn + 1, if(@item := item, 1, 1)) as rn
      from `data` d left join
           (select item, count(*) cnt
            from data
            group by item
           ) di
           on d.item = di.item cross join
           (select @rn := 0, @item := -1) vars
      order by item, price/quantity
     ) d
GROUP BY item;

【讨论】:

  • 查询未按原样运行。我假设“来自 dat”应该是“来自data”,我还必须标记最顶部的列。 (d.item、d.price 等)结果很接近。但是,当特定项目的行数
猜你喜欢
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-09
  • 2021-07-06
  • 2012-09-25
相关资源
最近更新 更多