我坚持这个问题。
基本上我需要找出每个部门如何确定哪些日子的销售额最高。结果显示部门编号和当天的日期,如果有几天的销售额相同,则部门编号可以在结果中多次显示。
这是我到目前为止所做的:
SELECT departmentNo, sDate FROM Department
HAVING MAX(sDate)
ORDER BY departmentNo, sDate;
我尝试使用max函数查找最常出现的日期。但它只返回一行值。为了澄清更多,销售最多的日期应该出现在名为departmentNo的相应列中。此外,如果部门A的两个日期具有相同数量的大部分销售额,那么部门A将出现两次,同时两个日期也会显示。
注意:只显示销售额最多的日期和departmentNo。
我已经启动了几个星期的SQL,但仍然很难掌握子查询和存储功能。但我会从经验中学习。提前谢谢。
更新:
结果我应该得到:
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
这些是数据:
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');
对于department1,将出现2012-05-18的日期,因为该日期发生的最多。对于每个部门,它应该只显示销售额最多的部门,如果同一日期出现相同数量的销售额,则两者都会出现,例如部门1将出现两次,同时包含最大销售日期。
答案 0 :(得分:2)
我已根据您提供的表和两列以及示例数据测试了以下查询。所以,让我为你描述一下。最内在的“PREQUERY”按部门和日期进行计数。这个结果将由部门首先预先订购,然后是DESCENDING ORDER中的最高数量(因此最高销售数量首先列出),计算发生的日期并不重要。
接下来,通过利用MySQL @variables,我预先声明了两个在查询中使用。 @variables就像使用MySQL进行内联编程一样。它们可以声明一次,然后根据应用于每个正在处理的记录进行更改。因此,我违反了虚假部门的价值和零销售额。
现在,我正在抓取PreQuery(Dept,#Sales和Date)的结果,但现在,添加一个测试。如果它是给定部门的FIRST ENTRY,请使用该记录的“NumberOfSales”并将其放入@maxSales变量并存储为最终列名“MaxSaleCnt”。下一列名称使用@lastDept,并设置为当前记录的Department#。所以它可以与下一个记录进行比较。
如果下一条记录是同一个部门,那么它只保留前一个@maxSales值,因此保持每个部门所有条目的第一个计数(*)结果相同。
现在,关闭。我添加了一个HAVING子句(不是WHERE,因为它限制了哪些记录被测试,但HAVING进程在记录是PROCESSED集的一部分之后。所以现在,它将拥有所有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,然后使用这个答案,否则使用这个答案)。
现在,上面的工作如何。让我们说以下是最内层查询返回的数据结果,由最顶层的销售人员进行分组和排序...从数据中略微改变,让我们假设以下内容来模拟部门上的多个日期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和@LastDept作为返回列的原因是必须为每个用于与NEXT记录进行比较的记录计算它们。该技术可用于许多应用目的。如果你点击我的名字,看看我的标签并点击MySQL标签,它会显示我回答的许多MySQL答案。他们中的许多人都使用@sqlvariables。此外,还有很多其他人非常善于处理查询,所以不要只看一个地方。至于任何问题,如果你找到一个有帮助的好答案,即使你没有发布问题,点击答案旁边的向上箭头也可以帮助其他人说明真正帮助他们理解的内容并解决问题 - - 再次,即使它不是你的问题。祝你的MySQL增长好运。
答案 1 :(得分: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