SQL:分组average-if / case SELECT语句

时间:2016-08-21 13:26:38

标签: mysql sql select average

我有一个看起来像这个SQL Fiddle的数据库:http://sqlfiddle.com/#!9/aa02e/1

CREATE TABLE Table1
    (`Store` varchar(1), `Date` date, `Product` varchar(2), `Weekday` int, `Month` int, `Revenue` float)
;

INSERT INTO Table1
    (`Store`, `Date`, `Product`, `Weekday`, `Month`, `Revenue`)
VALUES
    ('a', '20160101', 'aa', 5, 1, 1.5),
    ('a', '20160101', 'bb', 5, 1, 4),
    ('a', '20160101', 'cc', 5, 1, 3.5),
    ('a', '20160108', 'dd', 5, 1, 2.5),
    ('a', '20160108', 'ee', 5, 1, 5),
    ('b', '20160204', 'aa', 4, 2, 9.5),
    ('b', '20160204', 'bb', 4, 2, 4),
    ('b', '20160204', 'cc', 4, 2, 3),
    ('b', '20160211', 'dd', 4, 2, 1.5),
    ('b', '20160211', 'ee', 4, 2, 2.5)
;

 SELECT * FROM table1;
+-------+------------+---------+---------+-------+---------+
| Store | Date       | Product | Weekday | Month | Revenue |
+-------+------------+---------+---------+-------+---------+
| a     | 2016-01-01 | aa      |       5 |     1 |     1.5 |
| a     | 2016-01-01 | bb      |       5 |     1 |       4 |
| a     | 2016-01-01 | cc      |       5 |     1 |     3.5 |
| a     | 2016-01-08 | dd      |       5 |     1 |     2.5 |
| a     | 2016-01-08 | ee      |       5 |     1 |       5 |
| b     | 2016-02-04 | aa      |       4 |     2 |     9.5 |
| b     | 2016-02-04 | bb      |       4 |     2 |       4 |
| b     | 2016-02-04 | cc      |       4 |     2 |       3 |
| b     | 2016-02-11 | dd      |       4 |     2 |     1.5 |
| b     | 2016-02-11 | ee      |       4 |     2 |     2.5 |
+-------+------------+---------+---------+-------+---------+

显示商店的收入数据。产品,日期和相应的日/月。 我想选择以下内容:

  • 存储
  • 每月收入总额(即1月份商店a的总收入是多少?)
  • 平日收入平均值(即星期四商店a的平均收入是多少?)

第一个和第二个子弹是直截了当的,但我遇到了最后一个问题。 目前,它取所有产品和所有日期的平均值(假设工作日匹配)。我需要的是以下步骤:

  • 总结商店和特定日期的所有收入(例如商店b:2月4日9.5 + 4 + 3 = 16.5,2月11日1.5 + 2.5 = 4)如果该日期与工作日相同(此处周四)
  • 取两个值的平均值(例如avg(16.5,4)= 10.25)

我怎样才能做到这一点? 谢谢

以下是查询:

SELECT
  Store,
  SUM(CASE WHEN Month = 1 THEN Revenue ELSE NULL END) AS REVENUE_JAN,
  SUM(CASE WHEN Month = 2 THEN Revenue ELSE NULL END) AS REVENUE_FEB,
  AVG(CASE WHEN Weekday = 4 THEN Revenue ELSE NULL END) AS REVENUE_THU,
  AVG(CASE WHEN Weekday = 5 THEN Revenue ELSE NULL END) AS REVENUE_FRI
FROM Table1
GROUP BY
  Store
;

4 个答案:

答案 0 :(得分:1)

工作日平均水平很棘手。您的查询是获得每个工作日的平均“订单大小”。但是你想要总收入。

一种方法是首先按工作日聚合,但这有点乱。相反,您可以使用这个通过将总收入除以天数来计算平均值的技巧:

public class MyMapper extends HashMap {
    private String myProp;
    public void setMyProp(String myProp) {
        this.myProp = myProp;
    }
    public String getMyProp() {
        return myProp;
    }
}

答案 1 :(得分:1)

SELECT
  t1.store,
  SUM(CASE WHEN Month = 1 THEN Revenue ELSE NULL END) AS REVENUE_JAN,
  SUM(CASE WHEN Month = 2 THEN Revenue ELSE NULL END) AS REVENUE_FEB,
  daily.REVENUE_THU,
  daily.REVENUE_FRI
FROM Table1 t1
JOIN (
  SELECT
    Store,
    weekday,
    avg(CASE WHEN weekday = 4 THEN sum_rev END) as REVENUE_THU,
    avg(CASE WHEN weekday = 5 THEN sum_rev END) as REVENUE_FRI
  FROM (
    SELECT
      Store, date, weekday,
      SUM(revenue) AS sum_rev
    FROM Table1
    GROUP BY
      Store, date, weekday
  ) AS foo
  GROUP BY Store, weekday
) AS daily ON daily.store = t1.store
GROUP BY
  t1.store

答案 2 :(得分:0)

此解决方案如何为所选商店的所选日期返回平均值

CREATE PROCEDURE sumForDayStore(IN vday INTEGER, IN vStore VARCHAR(50))
BEGIN
    DECLARE totalDays INTEGER;
    DECLARE totalRevenu INTEGER;

    SET totalDays = (SELECT count(*) FROM Table1 WHERE WeekDay = vDay AND store = vStore);
    SET totalRevenu = (SELECT sum(Revenue) FROM Table1 WHERE WeekDay = vDay AND store = vStore);

    SELECT totalRevenu/totalDays;
END;

CALL sumForDayStore(5,'a');

答案 3 :(得分:0)

这个怎么样:

SELECT mnth.Store, REVENUE_JAN, REVENUE_FEB, avg(rthu) REVENUE_THU, avg(rfri) REVENUE_FRI
FROM 
(Select Store, sum(case when Month = 1 then Revenue else NULL END) REVENUE_JAN, 
sum(case when Month = 2 then Revenue else NULL END) REVENUE_FEB 
From Table1 group by Store) as mnth 

join 

(Select Store, sum(case when Weekday = 4 then Revenue end) rThu,
sum(case when Weekday = 5 then Revenue end) rFri from Table1 group by Store, Date) as dys 

on mnth.Store = dys.Store

group by mnth.Store, REVENUE_JAN, REVENUE_FEB

我将其性能与第一个答案中的查询进行了比较,并根据SQL服务器执行计划显示了更好的性能(快1.6倍)。也许这对更大的数据集会有所帮助。