2012-03-21 187 views
1

我有一個交易日期時間字段回溯數年的大量記錄。我想在今年和最後的同一時間段進行比較分析。我如何在一個3個月的範圍內按周分組?MySQL group by week

由於2012年的開始日期和2011年的開始日期,我遇到了使用YEARWEEK和WEEK功能的問題。

鑑於我從1月1日到當天每天都記錄日期時間,並且記錄的日期與上年相同,所以我如何按周分組,以便輸出的日期時間類似於:01/01/2011年1月8日,2011年1月15日等,以及01/01/2012,01/08/2012,01/15/2012等?

我的查詢到目前爲止如下:

SELECT 
    DATE_FORMAT(A.transaction_date, '%Y-%m-%d') as date, 
    ROUND(sum(A.quantity), 3) AS quantity, 
    ROUND(sum(A.total_amount), 3) AS amount, 
    A.product_code, 
    D.fuel_type_code, 
    D.fuel_type_name, 
    C.customer_code, 
    C.customer_name 
FROM 
    cl_transactions AS A 
INNER JOIN 
    card AS B ON A.card_number=B.card_number 
INNER JOIN 
    customer AS C ON B.customer_code=C.customer_code 
INNER JOIN 
    fuel_type AS D ON A.fuel_type=D.fuel_type_code 
WHERE 
    ((A.transaction_date >= DATE_FORMAT(NOW() - INTERVAL 3 MONTH, '%Y-%m-01')) OR (A.transaction_date - INTERVAL 1 YEAR >= DATE_FORMAT(NOW() - INTERVAL 15 MONTH, '%Y-%m-01') AND A.transaction_date <= NOW() - INTERVAL 1 YEAR)) 
GROUP BY 
    A.transaction_date, fuel_type_code; 

我會實質類似的東西,實現以下僞查詢:

GROUP BY 
    STARTING FROM THE OLDEST DATE (A.transaction_date + INTERVAL 6 DAY) 
+0

看起來你想MONTH和DAYOFMONTH()如果你想要的月份和日期匹配。 – 2012-03-21 17:09:46

+0

@MarcusAdams:我一直在研究這些日期函數,但我正在爲如何總結七天的小組而苦苦掙扎。 – btl 2012-03-21 17:15:54

回答

2

我開始與一個內部查詢使用sqlvariables打造出來的從今年和去年開始的年/月/日(分別爲2012-01-01和2011-01-01)的範圍。因此,我還會預格式化最終輸出的日期,以便您有一個主顯示日期,以反映「今年」每週的情況。

由此,我加入交易表,其中交易日期在本週開始和下週開始之間。由於日期/時間戳包括小時分鐘,因此2012-01-01本身暗示爲當天的12:00:00(午夜)。之間將在7天后的12:00:00上升。那個日期將成爲下一週的開始日期。

因此,通過加入日期在上一年或本年的時間段內,其具有相同的組合資格。所以現場選擇分別在去年或今年進行ROUND(SUM(IF()))。如果收到的交易日期比當年的周開始時間少,那麼它必須是前一年的記錄,否則是當年的記錄。因此,分別添加值本身,或者適用於零。

所以現在,你已經有了羣組。無論計算出的「YEARWEEK()」還是「WEEK()」,它都可以通過「ThisYearWeekOf」格式化列從內部查詢中準備好。日期範圍爲我們處理了這個資格。

最後,我添加了燃料類型作爲一個連接,並將其作爲一個組。您必須將所有非聚合列組合在一起才能獲得正確的SQL,儘管如果不在group by中指定,只需抓取給定組的第一個條目即可。

要關閉,我包含客戶的信息,因爲您沒有在組中使用它,似乎也不適用...它只會隨意抓取一個。不過,我已經將它添加到了該組中,所以現在您的記錄將顯示每個客戶級別,每種產品和燃料類型,今年和上次之間的銷售量和數量。

SELECT 
     JustWeekRange.ThisYearWeekOf, 
     CTrans.product_code, 
     FT.fuel_type_code, 
     FT.fuel_type_name, 
     C.customer_code, 
     C.customer_name, 
     ROUND(SUM(IF(CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, CTrans.Quantity, 0)), 3) as LastYrQty, 
     ROUND(SUM(IF(CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, CTrans.total_amount, 0)), 3) as LastYrAmt, 
     ROUND(SUM(IF(CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, 0, CTrans.Quantity)), 3) as ThisYrQty, 
     ROUND(SUM(IF(CTrans.transaction_date < JustWeekRange.ThisYrWeekStart, 0, CTrans.total_amount)), 3) as ThisYrAmt, 
    FROM 
     (SELECT 
       DATE_FORMAT(@ThisYearDate, '%Y-%m-%d') as ThisYearWeekOf, 
       @LastYearDate as LastYrWeekStart, 
       @ThisYearDate as ThisYrWeekStart, 
       @LastYearDate := date_add(@LastYearDate, interval 7 day) LastYrStartOfNextWeek, 
       @ThisYearDate := date_add(@ThisYearDate, interval 7 day) ThisYrStartOfNextWeek 
      FROM 
       (select @ThisYearDate := '2012-01-01', 
         @LastYearDate := '2011-01-01') sqlvars, 
       cl_transactions justForLimit 
      HAVING 
       ThisYrWeekStart < '2012-04-01' 
      LIMIT 15) JustWeekRange 

     JOIN cl_transactions AS CTrans 
     ON CTrans.transaction_date BETWEEN 
       JustWeekRange.LastYrWeekStart AND JustWeekRange.LastYrStartOfNextWeek 
      OR CTrans.transaction_date BETWEEN 
       JustWeekRange.ThisYrWeekStart AND JustWeekRange.ThisYrStartOfNextWeek 

     JOIN fuel_type FT 
     ON CTrans.fuel_type = FT.fuel_type_code 

     JOIN card 
     ON CTrans.card_number = card.card_number 
     JOIN customer AS C 
      ON card.customer_code = C.customer_code 

    GROUP BY 
     JustWeekRange.ThisYearWeekOf, 
     CTrans.product_code, 
     FT.fuel_type_code, 
     FT.fuel_type_name, 
     C.customer_code, 
     C.customer_name 
+0

聖牛,這真是太棒了!看起來它正在按照我的需要工作!非常感謝您抽出時間發佈此內容,並詳細解釋您所做的事情。非常感謝朋友! – btl 2012-03-21 17:35:02

+0

所以,它實際上工作?:) – DRapp 2012-03-21 17:46:15

+0

它看起來像它!我現在正在比較一些東西,看起來似乎加起來了。再一次,真的很感謝你的意見。 – btl 2012-03-21 18:06:07