【问题标题】:Getting sum of multiple columns and calculate each row's ratio获取多列的总和并计算每一行的比率
【发布时间】:2013-02-06 02:34:43
【问题描述】:

下面是我的 brand_of_items 表的架构。为简单起见,此处显示为两列:id(primary 和 AI),symbol(varchar 50,unique)

Table - brand_of_items
id   symbol
0    a
1    b
2    c
..   ..
10   j

下面是我的 items_of_brand 的架构。

Table - mainIndexQuantity
id  brand_of_items_id   vol  item_type  salefinalizeddate
0         1              5      0       2005-5-11
1         1              6      0       2004-5-11
2         1              7      0       2011-5-11
3         1              8      0       2011-5-12
4         1              9      0       2011-5-12
5         1              10     0       2011-5-11
6         1              5      1       2012-5-11
7         1              6      1       2012-5-11
8         1              7      1       2011-5-11
9         1              8      1       2010-5-12
10        1              9      1       2012-5-12
11        1              10     1       2005-5-12

mainIndexQuantity 表brand_of_items_id 列是指向brand_of_items (id) 的外键。 mainIndexQuantity 表 item_type 列不是外键,它应该是。

两种商品类型是:0 = 零售和 1 = 批发

我想计算每个 each_brand_of_items 表条目的商品类型(零售与批发)的比率。目标是查看某个品牌的商品是零售还是批发销售更多。


** 增加复杂性: 我想在 mainIndexQuantity 表中添加一个日期列,并希望找出 RetailVolume 和 WholesaleVolume 总和的差异,并按 salefinalizeddate 字段对结果进行分组。

这是为了帮助确定哪些商品在哪些季节销售得更多,RetailVolume 和 WholeSaleVolume 总和的 (delta) 差异将有助于选择最需要关注的商品。

【问题讨论】:

    标签: mysql sql sum pivot


    【解决方案1】:

    试试这个:

    SELECT 
      b.id,
      b.symbol,
      IFNULL(SUM(m.item_type = 1), 0) / (COUNT(*) * 1.0) AS wholesaleRatio,
      IFNULL(SUM(m.item_type = 0), 0) / (COUNT(*) * 1.0) AS RetailRatio
    FROM brand_of_items b
    LEFT JOIN mainIndexQuantity m ON b.id = m.brand_of_items_id
    GROUP BY b.id, 
             b.symbol;
    

    SQL Fiddle Demo.

    这会给你:

    | ID | SYMBOL | WHOLESALERATIO | RETAILRATIO |
    ----------------------------------------------
    |  0 |      a |              0 |           0 |
    |  1 |      b |            0.5 |         0.5 |
    |  2 |      c |              0 |           0 |
    | 10 |      j |              0 |           0 |
    

    假设:

    • wholesaleRatio 是 Whole sale 类型的商品数量到所有商品的数量。
    • RetailRatioretail 类型的项目的计数与所有项目的计数。

    如果这个比例是vol 列的总和与vol 的总和,你可以这样做:

    SELECT 
      b.id,
      b.symbol,
      SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) / SUM(m.vol) AS wholesaleRatio,
      SUM(CASE WHEN m.item_type = 0 THEN m.vol ELSE 0 END) / SUM(m.vol) AS RetailRatio
    FROM brand_of_items b
    LEFT JOIN mainIndexQuantity m ON b.id = m.brand_of_items_id
    GROUP BY b.id, 
             b.symbol;
    

    请注意:

    • 我使用了LEFT JOIN,因此您在结果集中得到了不匹配的行,即那些在MainIndexQuantity 表中没有条目的品牌项目。如果您不想包含它们,请改用INNER JOIN
    • 如@JW 所述,与1.0 相乘得到带小数位的计数。

    更新 1

    要包含Total VolumeRetail Volume SumWholesale Volume sum,试试这个:

    SELECT 
      b.id,
      b.symbol,
      IFNULL(SUM(m.item_type = 1), 0) * 1.0 / COUNT(*)     AS wholesaleRatio,
      IFNULL(SUM(m.item_type = 0), 0) * 1.0 / COUNT(*)     AS RetailRatio,
      IFNULL(SUM(m.vol), 0)                                AS 'Total Volume',
      SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS 'Retail Volume sum',
      SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS 'Wholesale Volume sum'
    FROM brand_of_items b
    LEFT JOIN mainIndexQuantity m ON b.id = m.brand_of_items_id
    GROUP BY b.id, 
             b.symbol;
    

    Updated SQL Fiddle Demo.

    这会给你:

    | ID | SYMBOL | WHOLESALERATIO | RETAILRATIO | TOTAL VOLUME | RETAIL VOLUME SUM | WHOLESALE VOLUME SUM |
    --------------------------------------------------------------------------------------------------------
    |  0 |      a |              0 |           0 |            0 |                 0 |                    0 |
    |  1 |      b |            0.5 |         0.5 |           90 |                45 |                   45 |
    |  2 |      c |              0 |           0 |            0 |                 0 |                    0 |
    | 10 |      j |              0 |           0 |            0 |                 0 |                    0 |
    

    如果你想按照这些总数和总和对结果集进行排序,把这个查询放在一个子查询中,那么你可以这样做:

    SELECT *
    FROM
    (
       SELECT 
          b.id,
          b.symbol,
          IFNULL(SUM(m.item_type = 1), 0) * 1.0 / COUNT(*)     AS wholesaleRatio,
          IFNULL(SUM(m.item_type = 0), 0) * 1.0 / COUNT(*)     AS RetailRatio,
          IFNULL(SUM(m.vol), 0)                                AS TotalVolume,
          SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS RetailVolumeSum,
          SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS WholesaleVolumeSum
        FROM brand_of_items b
        LEFT JOIN mainIndexQuantity m ON b.id = m.brand_of_items_id
        GROUP BY b.id, 
                 b.symbol
    ) AS sub
    ORDER BY RetailVolumeSum    DESC, 
             WholesaleVolumeSum DESC;
    

    但是您最后的要求并不清楚,您是在寻找那些具有最高的retio/wholesale ratis 和volumns 的品牌还是选择它们中的最高值?

    对于后一个:

    SELECT *
    FROM
    (
       SELECT 
          b.id,
          b.symbol,
          IFNULL(SUM(m.item_type = 1), 0) * 1.0 / COUNT(*)     AS wholesaleRatio,
          IFNULL(SUM(m.item_type = 0), 0) * 1.0 / COUNT(*)     AS RetailRatio,
          IFNULL(SUM(m.vol), 0)                                AS TotalVolume,
          SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS RetailVolumeSum,
          SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS WholesaleVolumeSum
        FROM brand_of_items b
        LEFT JOIN mainIndexQuantity m ON b.id = m.brand_of_items_id
        GROUP BY b.id, 
                 b.symbol
    ) AS sub
    ORDER BY RetailVolumeSum    DESC, 
             WholesaleVolumeSum DESC,
             TotalVolume        DESC
    LIMIT 1;
    

    更新 2

    要获得总销量最高的品牌,您可以这样做:

    SELECT 
      b.id,
      b.symbol,
      IFNULL(SUM(m.item_type = 1), 0) * 1.0 / COUNT(*)     AS wholesaleRatio,
      IFNULL(SUM(m.item_type = 0), 0) * 1.0 / COUNT(*)     AS RetailRatio,
      IFNULL(SUM(m.vol), 0)                                AS TotalVolume,
      SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS RetailVolumeSum,
      SUM(CASE WHEN m.item_type = 1 THEN m.vol ELSE 0 END) AS WholesaleVolumeSum
    FROM brand_of_items b
    LEFT JOIN mainIndexQuantity m ON b.id = m.brand_of_items_id
    GROUP BY b.id, 
             b.symbol
    HAVING SUM(m.vol) = (SELECT MAX(TotalVolume)
                         FROM
                         (
                           SELECT brand_of_items_id, SUM(vol) AS TotalVolume
                           FROM mainIndexQuantity
                           GROUP BY brand_of_items_id
                         ) t);
    

    Like this.

    请注意:

    • 这将为您提供总销量最高的品牌,如果您正在寻找具有最高比率的品牌,您必须替换having子句以获得比率的最大值而不是最大值总音量。

    • 这将为您提供总数量最高的项目,因此您可能希望拥有多个项目,以防多个项目的总数量最高,例如 this updated fiddle demo。在这种情况下,要只得到一个,你必须使用LIMIT 来只返回一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-08
      • 2020-08-24
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 2020-07-26
      相关资源
      最近更新 更多