MySQL 查询使用多个表中的数据计算最新的平均价格

标签 mysql

我正在开发一个基于 PHP 和 MySQL 的系统来组织餐厅的产品和费用。

我将数据组织成四个表。

项目表

id | name
1  | Beer
2  | Vodka

产品表

id | item_id | name
1  |    1    | Budweiser
2  |    1    | Sam Adams
3  |    2    | Smirnoff
4  |    2    | Grey Goose

供应商表

id | name
1  | Supplier 1
2  | Supplier 2

费用表

id | product_id | cost | quantity | supplier | date
1  |     1      | 2.99 |     1    |     1    |  2017-09-05
2  |     1      | 3.00 |     2    |     2    |  2017-09-10
3  |     1      | 2.50 |     1    |     1    |  2017-09-20
4  |     1      | 3.98 |     2    |     1    |  2017-09-22
5  |     1      | 4.00 |     1    |     2    |  2017-09-25
6  |     1      | 8.00 |     2    |     2    |  2017-09-27

我想编写一个 MYSQL 查询,它可以根据费用表(基于日期)中最新 3 个整体的每件商品的平均成本(成本/数量)找出特定产品的最便宜供应商。

这是我要计算的内容:

供应商 1 最后 3 个条目 - 单位成本:2.99、2.50 和 1.99。平均值 = 2.49

供应商 2 最后 3 个条目 - 单位成本:1.50、4.00 和 4.00。平均值 = 3.16

因此 SQL 应该返回供应商 1 是产品 1(百威)最便宜的选择。

到目前为止我已经尝试过了,但我有点迷茫和困惑:

select * from products 
INNER JOIN expenses
ON products.id = expenses.product
AND products.item = '1'
ORDER BY (expenses.cost/expenses.quantity)
LIMIT 3;

这个查询的输出与我想要弄清楚的结果相去甚远:(:

id | item_id |  name   | id | product_id | cost | quantity | supplier | date
1  |    1    |Budweiser| 2  |     1      | 3.00 |    2     |    2     | 2017-09-10
1  |    1    |Budweiser| 4  |     1      | 3.98 |    2     |    1     | 2017-09-22
1  |    1    |Budweiser| 3  |     1      | 2.50 |    1     |    1     | 2017-09-20

我根据示例数据寻找的输出是:

cheapest_supplier
        1

最佳答案

I would like to write a MYSQL Query that can figure out the cheapest supplier of a specific product based on the average cost per item (cost/quantity) of the latest 3 entires in the expenses table (based on date).

一个选项将是一个查询,它与用户变量一起使用以生成基于日期的排名。 并且只选择最后三个日期。

查询

SELECT 
 *
FROM (
   SELECT 
   * 
   , CASE 
       WHEN @supplier = supplier
       THEN @rank := @rank + 1 
       ELSE @rank := 1
     END 
      AS rank
   , @supplier := supplier 
   FROM 
     Expenses 
   CROSS JOIN (
    SELECT
       @supplier := NULL
     , @rank := 0
    ) 
    AS
      init_user_params  
   WHERE
      product_id = 1       
   ORDER BY
      supplier ASC 
    , DATE DESC   
)
 AS Expenses_ranked 
WHERE
  Expenses_ranked.rank <= 3

结果

    id  product_id  cost    quantity  supplier  date        @supplier := NULL  @rank := 0    rank  @supplier := supplier  
------  ----------  ------  --------  --------  ----------  -----------------  ----------  ------  -----------------------
     4           1  3.98           2         1  2017-09-22  (NULL)                      0       1                        1
     3           1  2.50           1         1  2017-09-20  (NULL)                      0       2                        1
     1           1  2.99           1         1  2017-09-05  (NULL)                      0       3                        1
     6           1  8.00           2         2  2017-09-27  (NULL)                      0       1                        2
     5           1  4.00           1         2  2017-09-25  (NULL)                      0       2                        2
     2           1  3.00           2         2  2017-09-10  (NULL)                      0       3                        2

使用该结果生成每个供应商的平均列表。

查询

SELECT 
   Expenses_ranked.supplier 
 , AVG(Expenses_ranked.cost / Expenses_ranked.quantity) AS AVG
FROM ( 

  SELECT 
   * 
   , CASE 
       WHEN @supplier = supplier
       THEN @rank := @rank + 1 
       ELSE @rank := 1
     END 
      AS rank
   , @supplier := supplier 
   FROM 
     Expenses 
   CROSS JOIN (
    SELECT
       @supplier := NULL
     , @rank := 0
    ) 
    AS
      init_user_params  
   WHERE
      product_id = 1       
   ORDER BY
      supplier ASC 
    , DATE DESC   
)
 AS Expenses_ranked 
WHERE
  Expenses_ranked.rank <= 3
GROUP BY
  Expenses_ranked.supplier 

结果

supplier  avg           
--------  --------------
       1  2.4933333333  
       2  3.1666666667  

现在我们可以使用一个简单的 ORDER BY [] ASC LIMIT 1 来获得最便宜的供应商

查询

SELECT 
 Expenses_ranked_avg.supplier AS cheapest_supplier
FROM ( 

  SELECT 
     Expenses_ranked.supplier 
   , AVG(Expenses_ranked.cost / Expenses_ranked.quantity) AS AVG
  FROM ( 

    SELECT 
     * 
     , CASE 
         WHEN @supplier = supplier
         THEN @rank := @rank + 1 
         ELSE @rank := 1
       END 
      AS rank
   , @supplier := supplier 
   FROM 
     Expenses 
   CROSS JOIN (
    SELECT
       @supplier := NULL
     , @rank := 0
    ) 
    AS
      init_user_params  
   WHERE
      product_id = 1       
   ORDER BY
      supplier ASC 
    , DATE DESC   
    )
      AS
        Expenses_ranked 
    WHERE
      Expenses_ranked.rank <= 3
    GROUP BY
      Expenses_ranked.supplier 
)
  AS Expenses_ranked_avg 
ORDER BY 
 Expenses_ranked_avg.avg ASC
LIMIT 1

结果

cheapest_supplier  
-------------------
                  1

更优化的查询。

还可以在 where 语句中声明用户变量。 可以直接过滤掉排名。

查询

  SELECT 
   *
  FROM
   Expenses 
  WHERE
   (
     CASE 
       WHEN @supplier = supplier
       THEN @rank := @rank + 1 
       ELSE @rank := 1
     END  
   ) 
 AND
   (@supplier := supplier )
 AND  
   @rank <= 3  
 AND  
   product_id = 1
ORDER BY 
   supplier ASC
 , DATE ASC  

结果

    id  product_id  cost    quantity  supplier  date        
------  ----------  ------  --------  --------  ------------
     1           1  2.99           1         1  2017-09-05  
     3           1  2.50           1         1  2017-09-20  
     4           1  3.98           2         1  2017-09-22  
     2           1  3.00           2         2  2017-09-10  
     5           1  4.00           1         2  2017-09-25  
     6           1  8.00           2         2  2017-09-27 

现在使用此结果集可以轻松找到最便宜的供应商。

查询

SELECT 
   Expenses_ranked.supplier AS cheapest_supplier
FROM (  

  SELECT 
   *
  FROM
   Expenses 
  WHERE
   (
     CASE 
       WHEN @supplier = supplier
       THEN @rank := @rank + 1 
       ELSE @rank := 1
     END  
   ) IS NOT NULL 
 AND
   (@supplier := supplier ) IS NOT NULL
 AND  
   @rank <= 3  
 AND  
   product_id = 1
ORDER BY 
   supplier ASC
 , DATE ASC  
)
 AS Expenses_ranked 
GROUP BY
  Expenses_ranked.supplier
ORDER BY 
  AVG(Expenses_ranked.cost / Expenses_ranked.quantity) ASC
LIMIT 1  

结果

cheapest_supplier  
-------------------
                  1

关于MySQL 查询使用多个表中的数据计算最新的平均价格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46514359/

相关文章:

php 显示一个 COUNT 的结果?我认为

php - 使用 PHP 搜索存储在 mySql 列中的数组的最快方法

php - Symfony findOneBy : column type array returns null

mysql - 无法将表字符集编码从 latin1_swedish_ci 更改为 utf8mb4_bin

mysql 将 float 与 in 子句进行比较

java - 无法解析配置 :/hibernate. cfg.xml hibernate.sourceforge.net

mysql - Node.js 中的存储过程有时不返回值

mysql - MySQL InnoDB 表之间的外键不起作用...为什么?

mysql - 从一个表中选择,而不是在另一个表中

mysql - docker-compose 未知 MySQL 服务器主机 'mysql'( Airflow )