2

I'm stuck on this problem.

Basically I need to find out for each department how to figure out which days had the most sales made in them. The results display the department number and the date of the day and a department number can appear several times in the results if there were several days that have equally made the most sales.

This is what I have so far:

SELECT departmentNo, sDate FROM Department
HAVING MAX(sDate)
ORDER BY departmentNo, sDate;

I tried using the max function to find which dates occurred most. But it only returns one row of values. To clarify more, the dates that has the most sales should appear with the corresponding column called departmentNo. Also, if two dates for department A has equal amount of most sales then department A would appear twice with both dates showing too.

NOTE: only dates with the most sales should appear and the departmentNo.

I've started mySQL for few weeks now but still struggling to grasp the likes of subqueries and store functions. But i'll learn from experiences. Thank you in advance.

UPDATED:

Results I should get:

DepartmentNo Column 1: 1 | Date Column 2: 15/08/2000 
DepartmentNo Column 1: 2 | Date Column 2: 01/10/2012 
DepartmentNo Column 1: 3 | Date Column 2: 01/06/1999 
DepartmentNo Column 1: 4 | Date Column 2: 08/03/2002 
DepartmentNo Column 1: nth | Date Column 2: nth date

These are the data:

INSERT INTO Department VALUES ('1','tv','2012-05-20','13:20:01','19:40:23','2');
INSERT INTO Department VALUES ('2','radio','2012-07-22','09:32:23','14:18:51','4');
INSERT INTO Department VALUES ('3','tv','2012-09-14','15:15:43','23:45:38','3');
INSERT INTO Department VALUES ('2','tv','2012-06-18','06:20:29','09:57:37','1');
INSERT INTO Department VALUES ('1','radio','2012-06-18','11:34:07','15:41:09','2');
INSERT INTO Department VALUES ('2','batteries','2012-06-18','16:20:01','23:40:23','3');
INSERT INTO Department VALUES ('2','remote','2012-06-18','13:20:41','19:40:23','4');
INSERT INTO Department VALUES ('1','computer','2012-06-18','13:20:54','19:40:23','4');
INSERT INTO Department VALUES ('2','dishwasher','2011-06-18','13:20:23','19:40:23','4');
INSERT INTO Department VALUES ('3','lawnmower','2011-06-18','13:20:57','20:40:23','4');
INSERT INTO Department VALUES ('3','lawnmower','2011-06-18','11:20:57','20:40:23','4');
INSERT INTO Department VALUES ('1','mobile','2012-05-18','13:20:31','19:40:23','4');
INSERT INTO Department VALUES ('1','mouse','2012-05-18','13:20:34','19:40:23','4');
INSERT INTO Department VALUES ('1','radio','2012-05-18','13:20:12','19:40:23','4');
INSERT INTO Department VALUES ('2','lawnmowerphones','2012-05-18','13:20:54','19:40:23','4');
INSERT INTO Department VALUES ('2','tv','2012-05-12','06:20:29','09:57:37','1');
INSERT INTO Department VALUES ('2','radio','2011-05-23','11:34:07','15:41:09','2');
INSERT INTO Department VALUES ('1','batteries','2011-05-21','16:20:01','23:40:23','3');
INSERT INTO Department VALUES ('2','remote','2011-05-01','13:20:41','19:40:23','4');
INSERT INTO Department VALUES ('3','mobile','2011-05-09','13:20:31','19:40:23','4');

For department1 the date 2012-05-18 would appear because that date occurred the most. And for every department, it should only show the one with the most sales, and if same amount of sales appears on the same date then both will appear, e.g. Department 1 will appear twice with both the dates of max sales.

4

2 回答 2

2

我已经根据您提供的表格和两列以及示例数据测试了以下查询。所以,让我为你描述一下。最里面的“PREQUERY”正在按部门和日期进行计数。其结果将首先由部门预订,然后是 DESCENDING ORDER 中的最高计数(因此最高销售计数首先列出),计数发生的日期无关紧要。

接下来,通过利用 MySQL @variables,我预先声明了两个要在查询中使用。@variables 类似于 MySQL 的内联编程。它们可以声明一次,然后更改为应用于正在处理的每个记录。所以,我默认使用虚假的部门价值和零销售计数。

现在,我正在获取 PreQuery 的结果(Dept、#Sales 和 Date),但现在,添加了一个测试。如果它是给定部门的第一个条目,请使用该记录的“NumberOfSales”并放入@maxSales 变量并存储为最终列名“MaxSaleCnt”。下一个列名使用@lastDept 并设置为当前记录的部门编号。因此可以与下一条记录进行比较。

如果下一个记录是同一个部门,那么它只保留前一个记录的 @maxSales 值,从而为每个相应部门的所有条目保持相同的第一个 count(*) 结果。

现在,关闭。我添加了一个 HAVING 子句(不是 WHERE,因为它限制了测试的记录,但是在记录是 PROCESSED 集的一部分之后的 HAVING 进程。所以现在,它将包含所有 5 列。我说只保留那些记录记录的最终 NumberOfSales 与部门的 MaxSaleCnt 匹配。如果有一个、两个或多个日期,没问题,它会根据各个部门返回所有日期。

因此,一个部门可以有 5 个日期,每个日期有 10 个销售额,另一个部门有 2 个日期,每个日期只有 3 个销售额,另一个部门只有 1 个日期,每个日期有 6 个销售额。

select
      Final.DepartmentNo,
      Final.NumberOfSales,
      Final.sDate
   from
      (select
          PreQuery.DepartmentNo,
          PreQuery.NumberOfSales,
          PreQuery.sDate,
          @maxSales := if( PreQuery.DepartmentNo = @lastDept, @maxSales, PreQuery.NumberOfSales ) MaxSaleCnt,
          @lastDept := PreQuery.DepartmentNo
       from
          ( select
                  D.DepartmentNo,
                  D.sDate,
                  count(*) as NumberOfSales
               from
                  Department D
               group by
                  D.DepartmentNo,
                  D.sDate
               order by
                  D.DepartmentNo,
                  NumberOfSales DESC ) PreQuery,
          ( select @lastDept := '~',
                   @maxSales := 0 ) sqlvars
       having
          NumberOfSales = MaxSaleCnt ) Final

根据您的最终评论澄清“@”和“~”。“@”表示可以在查询中使用的程序的局部变量(或者在这种情况下是内联 sql 变量)。'~' 只不过是一个简单的字符串,概率永远不会存在于你的任何部门,所以当它与第一个合格的记录进行比较时,做一个 IF('~' = YourFirstDepartmentNumber,然后使用这个答案,否则使用这个答案)。

现在,上面的工作是如何工作的。假设以下是最内层查询返回的数据的结果,按顶部最多的销售额进行分组和排序...稍微改变了您的数据,让我们假设以下内容来模拟 Dept 上的多个日期2个销量相同的...

Row#   DeptNo  Sales Date     # Sales
1      1       2012-05-18        3
2      1       2012-06-18        2
3      1       2012-05-20        1

4      2       2012-06-18        4
5      2       2011-05-23        4
6      2       2012-05-18        2
7      2       2012-05-12        1

8      3       2011-06-18        2
9      3       2012-09-14        1

跟踪实际行。以别名“PreQuery”结束的最内层查询按您在此处看到的顺序返回所有行。然后,它与 @ sqlvariables 的声明(对于 MySQL 是特殊的,其他 sql 引擎不这样做)加入(隐含)并以 lastDept = '~' 和 maxSales = 0 开始它们的值(通过 @someVariable 赋值: = 这边的结果)。现在,将上述内容视为

DO WHILE WE HAVE RECORDS LEFT
   Get the department #, Number of Sales and sDate from the record.

   IF the PreQuery Record's Department # = whatever is in the @lastDept
      set MaxSales = whatever is ALREADY established as max sales for this dept
      This basically keeps the MaxSales the same value for ALL in the same Dept #
   ELSE
      set MaxSales = the # of sales since this is a new department number and is the highest count
   END IF

   NOW, set @lastDept = the department you just processed to it 
   can be compared when you get to the next record.

   Skip to the next record to be processed and go back to the start of this loop
END DO WHILE LOOP

现在,您需要将@MaxSales 和THEN 的@LastDept 作为返回列的原因是必须为每条记录计算它们以用于与NEXT 记录进行比较。这种技术可以用于许多应用目的。如果你点击我的名字,查看我的标签,然后点击 MySQL 标签,它会显示我已经回复的许多 MySQL 答案。其中许多确实使用@sqlvariables。此外,还有很多其他人非常擅长处理查询,所以不要只看一个地方。对于任何问题,如果您找到一个对您有帮助的好答案,即使您没有发布问题,单击答案旁边的向上箭头也可以帮助其他人指出真正帮助他们理解和解决问题的内容 - - 再次,即使它不是你的问题。祝你的 MySQL 成长好运。

于 2012-12-01T04:33:30.253 回答
1

我认为这可以通过单个查询来实现,但我对类似功能的经验涉及使用 Oracle 或 MSSQL 的 WITH(如 SQL'99 中定义)。

解决此类问题的最佳(唯一?)方法是分解成更小的组件。(我认为您提供的声明并未提供所有列,因此我将不得不做出一些假设。)

首先,每个组每天的销售额是多少:

SELECT department, COUNT(1) AS dept_count, sale_date
FROM orders
GROUP BY department, sale_date

接下来,每个部门的销售额最高是多少

SELECT tmp.department, MAX(tmp.dept_count)
FROM (
    SELECT department, COUNT(1) AS dept_count
    FROM orders
    GROUP BY department
) AS tmp
GROUP BY tmp.department

最后,将两者放在一起:

 SELECT a.department, a.dept_count, b.sale_date
 FROM (
    SELECT tmp.department, MAX(tmp.dept_count) AS max_dept_count
    FROM (
       SELECT department, COUNT(1) AS dept_count
       FROM orders
       GROUP BY department
    ) AS tmp
    GROUP BY tmp.department
 ) AS a
 JOIN (
    SELECT department, COUNT(1) AS dept_count, sale_date
    FROM orders
    GROUP BY department, sale_date
 ) AS b
    ON a.department = b.department
       AND a.max_dept_count = b.dept_count
于 2012-12-01T02:08:17.043 回答