MySQL查询使用来自多个表

时间:2017-10-01 16:21:23

标签: 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个项目的平均每项成本(成本/数量),找出最便宜的特定产品供应商。< / p>

这是我想要计算的内容:

供应商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

2 个答案:

答案 0 :(得分:4)

  

我想编写一个MYSQL查询,可以根据每个平均成本计算出最便宜的特定产品供应商   费用表中最新3个项目的项目(成本/数量)   (根据日期而定)。

这将需要一个与用户变量一起使用的查询,以根据日期生成排名。 并且只选择最后三个日期。

<强>查询

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

答案 1 :(得分:1)

E.g:

SELECT x.product_id
     , x.supplier_id
     , x.date
     , ROUND(AVG(y.cost/y.quantity),2) total_cost
  FROM expenses x 
  JOIN expenses y 
    ON y.product_id = x.product_id 
   AND y.supplier_id = x.supplier_id
   AND y.date <= x.date 
 GROUP 
    BY product_id
     , supplier_id
     , date 
HAVING COUNT(*) = 3;