2012-12-01 61 views
2

我被困在這個問題上。MySQL - 特定日期最常見的?

基本上我需要找出每個部門如何找出哪些天銷售最多的日子。結果將顯示部門編號和當天的日期,如果有幾天的銷售額同樣最多,則部門編號可能會在結果中出現多次。

這是我到目前爲止有:

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

我嘗試使用max函數找到其歷史發生最多。但它只返回一行值。爲了更清楚地說明,銷售額最高的日期應與名爲departmentNo的相應列一起顯示。此外,如果部門A的兩個日期具有相等的大部分銷售額,那麼部門A會出現兩次,並且兩個日期都顯示出來。

注意:只有銷售量最大的日期纔會顯示,並且部門號碼爲。

我已經開始了幾個星期的mySQL,但仍然努力去掌握子查詢和存儲功能。但我會從經驗中學習。先謝謝你。

更新:

結果,我應該得到:

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

關於你的餐桌。是的,一個部門表,但銷售表呢?它是否每天有1筆銷售總額,或者它像是一個「訂單」表,其中有很多銷售金額和相應的日期需要SUM()編輯?根據您對此的回答添加額外的圖層查詢...此外,顯示銷售表的樣本數據也會有所幫助。 – DRapp

+0

請忽略銷售表。對不起,我這個構思不好的問題。假設部門1有3個日期:01/01/2001,01/01/2001和12/08/2009。我應該得到日期爲01/01/2001的結果列,因爲這發生了兩次,而2009年12月8日不會顯示,因爲這不是最常發生的日期。因此,這些列應該是:theatreNo = 1和date = 01/01/2001。另外如果發生2次的日期相同,那麼該部門將出現兩次。銷售不需要考慮日期和部門號。 –

+0

PS:對於每個部門,我們發現它所屬的每個部門的發生最多的日期。 –

回答

2

我已經根據您提供的表格和兩列以及示例數據測試了以下查詢。所以,讓我爲你描述它。最內層的「PREQUERY」按部門和日期進行計數。這個結果將由部門預先訂購,然後是降低訂單的最高數量(因此最高銷售數量列在第一位),計數發生的日期並不重要。

接下來,通過使用MySQL @variables,我預先聲明瞭兩個用於查詢。 @變量就像使用MySQL進行內聯編程。它們可以聲明一次,然後更改爲適用於每個正在處理的記錄。所以,我違背虛假部門價值和零銷售數量。

現在,我抓住了PreQuery(Dept,#Sale和Date)的結果,但現在添加了一個測試。如果它是給定部門的第一個入口,則使用該記錄的「NumberOfSales」並放入@maxSales變量中,並將其存儲爲最終列名「MaxSaleCnt」。下一列名稱使用@lastDept,並設置爲當前記錄的部門號。所以它可以與下一個記錄進行比較。

如果下一個記錄是同一個部門,那麼它只是保留@maxSales值與前一個值相同,從而爲每個部門的所有條目保留相同的第一個計數(*)結果。

現在,關閉。我已經添加了一個HAVING子句(不是WHERE,因爲它限制了什麼記錄被測試,但是HAVING過程之後的記錄是PROCESSED集合的一部分,所以現在它將包含所有5個列,我只是說把這些記錄保存在哪裏該記錄的最後NumberOfSales相匹配的部門MaxSaleCnt。如果一個,兩個或更多的日期,沒有問題,它返回他們都按各自的部門。

所以,一個部門可以有5個日期每10個銷售,而另一部門有兩個日期,每個只有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成長。

+0

這個作品就像我想要的,謝謝。然而,有沒有一種方法,結果沒有列的NumberOfSales,MaxSaleCnt和lastDept? –

+0

@AjayPunja,是的,只是把它包起來一層(我編輯答案)只抓住這些字段。注意第一個查詢如何完全(包裝)最終別名。 – DRapp

+0

謝謝。你能否詳細說明我很難理解的幾點,因爲這塊代碼是相當先進的(最近纔開始理解聯接和子查詢)。 @符號代表什麼以及做什麼,以及〜波浪線。同樣對於您的IF語句,這是存儲過程的一部分嗎?我們還沒有實施任何程序語言。如果你能澄清這些問題,我將不勝感激。謝謝。 –

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 
+0

這與我想要的非常接近,您答案的第一部分計算特定日期的department_no銷售量的多少倍。然而,第二部分似乎有些不正確,它並不顯示每個部門的銷售額最高,而是每個部門的總銷售額。 –

+0

第二部分(b)按日期重新確定每個部門的銷售數量。然後,將這些結果返回到部門(a)的最高銷售額允許查詢生成一個集合,顯示每個部門的最大銷售數量以及銷售發生的相應日期。 – KDrewiske