2012-01-06 58 views
0

我有我試圖執行一個查詢的以下三個表:MySQL的GROUP BY和限制加入

訂單

id 

created_at 

id 

order_id 

initial_value 

current_value 

vouchers_used_in_orders

voucher_id 

order_id 

amount_used 

value_before 

value_after 

憑證是在訂單中購買的,然後將此訂單的ID保存到憑證以保存購買時間的記錄。

在以後的日期,可以使用憑證以其他訂單購買商品。每張憑證都有現金價值,因此可以按多個訂單使用,直到其價值完全用完爲止。

我試圖想出一個查詢,它將按購買的年份和月份對購買憑證進行分組,並顯示有多少人被購買,並且在他們第一次使用之前已經花了多少時間,最多用了12個月。

這是我到目前爲止有:

SELECT 
YEAR(o.created_at) AS year_purchased, 
MONTH(o.created_at) AS month_purchased, 
SUM(IF(v.current_value = v.initial_value, 1, 1)) AS number_sold, 
SUM(IF(v.current_value = v.initial_value, 0, 1)) AS number_used, 
SUM(IF(v.current_value = v.initial_value, 1, 0)) AS number_not_used, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at) AND MONTH(vuo.created_at) = (MONTH(o.created_at)), 1, 0)) AS number_used_month_0, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 1 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 1 MONTH)), 1, 0)) AS number_used_month_1, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 2 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 2 MONTH)), 1, 0)) AS number_used_month_2, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 3 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 3 MONTH)), 1, 0)) AS number_used_month_3, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 4 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 4 MONTH)), 1, 0)) AS number_used_month_4, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 5 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 5 MONTH)), 1, 0)) AS number_used_month_5, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 6 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 6 MONTH)), 1, 0)) AS number_used_month_6, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 7 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 7 MONTH)), 1, 0)) AS number_used_month_7, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 8 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 8 MONTH)), 1, 0)) AS number_used_month_8, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 9 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 9 MONTH)), 1, 0)) AS number_used_month_9, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 10 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 10 MONTH)), 1, 0)) AS number_used_month_10, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 11 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 11 MONTH)), 1, 0)) AS number_used_month_11, 
SUM(IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 12 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 12 MONTH)), 1, 0)) AS number_used_month_12 
FROM vouchers v 
INNER JOIN orders o 
ON o.id = v.order_id 
LEFT OUTER JOIN vouchers_used_in_orders vu 
ON vu.voucher_id = v.id 
LEFT OUTER JOIN orders vuo 
ON vuo.id = vu.id 
GROUP BY 
YEAR(o.created_at), MONTH(o.created_at) 
ORDER BY 
YEAR(o.created_at), MONTH(o.created_at) 

這正確地計算所購買的憑證,如果他們沒有被然而,一旦他們開始習慣於使用時,外部聯接導致憑證多次計算。此外,它還計算每次使用優惠券的時間,當我只想要第一次使用時。

任何人都可以幫忙嗎?

任何意見讚賞。

謝謝。

回答

1

您可以在憑證ID上使用COUNT DISTINCT嗎? (您將需要設置虛假情況的,如果讓他們不計語句來爲null)

SELECT 
YEAR(o.created_at) AS year_purchased, 
MONTH(o.created_at) AS month_purchased, 
SUM(IF(v.current_value = v.initial_value, 1, 1)) AS number_sold, 
SUM(IF(v.current_value = v.initial_value, 0, 1)) AS number_used, 
SUM(IF(v.current_value = v.initial_value, 1, 0)) AS number_not_used, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at) AND MONTH(vuo.created_at) = (MONTH(o.created_at)), vuo.voucher_id, null)) AS number_used_month_0, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 1 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 1 MONTH)), vuo.voucher_id, null)))) AS number_used_month_1, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 2 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 2 MONTH)), vuo.voucher_id, null)))) AS number_used_month_2, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 3 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 3 MONTH)), vuo.voucher_id, null)))) AS number_used_month_3, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 4 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 4 MONTH)), vuo.voucher_id, null)))) AS number_used_month_4, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 5 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 5 MONTH)), vuo.voucher_id, null)))) AS number_used_month_5, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 6 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 6 MONTH)), vuo.voucher_id, null)))) AS number_used_month_6, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 7 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 7 MONTH)), vuo.voucher_id, null)))) AS number_used_month_7, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 8 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 8 MONTH)), vuo.voucher_id, null)))) AS number_used_month_8, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 9 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 9 MONTH)), vuo.voucher_id, null)))) AS number_used_month_9, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 10 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 10 MONTH)), vuo.voucher_id, null)))) AS number_used_month_10, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 11 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 11 MONTH)), vuo.voucher_id, null)))) AS number_used_month_11, 
COUNT(DISTINCT IF(YEAR(vuo.created_at) = YEAR(o.created_at + INTERVAL 12 MONTH) AND MONTH(vuo.created_at) = (MONTH(o.created_at + INTERVAL 12 MONTH)), vuo.voucher_id, null)))) AS number_used_month_12 
FROM vouchers v 
INNER JOIN orders o 
ON o.id = v.order_id 
LEFT OUTER JOIN vouchers_used_in_orders vu 
ON vu.voucher_id = v.id 
LEFT OUTER JOIN orders vuo 
ON vuo.id = vu.id 
GROUP BY 
YEAR(o.created_at), MONTH(o.created_at) 
ORDER BY 
YEAR(o.created_at), MONTH(o.created_at) 
0

我會結合「券」和「訂單」到:

voucher_orders: 
    ID 
    purchase_date 
    value 

然後有 'voucher_use':

 VoucherID 
    Amount 
    use_date 

爲了得到統計:

select voucher_order.ID as v0, voucher_order.purchase_date, v2.ud left join 
( select min(use_date) ud from voucher_use as v1 where v1.VoucherID = v0.VoucherID limit 1) as v2 on v0.VoucherID = v2.VoucherID group by v0.purchase_date order by v0.purchase_date; 

在代碼中做所有'剩餘價值'的東西。此信息不需要存儲。

1

這應該給你幾乎所有你正在尋找。除了每月計數外,我還增加了每月使用的總數。我首先開始查詢以獲得優惠券,初始日期以及每個關注點加上12個月的費用。我在每個「每個憑證」的基礎上預先計算一次月份,這樣可以幫助簡化彙總的SUM(IF())構造。爲了檢測憑證的單一計數,在我的預查(V1)中,我保留了與購買憑證相關的原始訂單。所以通過使用它,我可以做一個SUM(IF())相同的訂單ID。如果是其中的一個,它將被計入憑證使用中。使用憑證使用表的左連接,如果返回爲空,則沒有使用它的實例,並且將是NULL值。

您會注意到,我還採取了一項預防措施,通過明確禁止用於購買憑證的訂單ID被計數並錯誤地丟棄計數,以防止通過LEFT JOIN包括原始訂單。

LEFT JOIN Vouchers_Used_In_Orders VUIO 
    ON V1.ID = VUIO.Voucher_ID 
    AND NOT V1.OriginalOrderID = VUIO.Order_ID 

的唯一元件,我不能真正測試,和不具有的MySQL現在是

SUM(IF(VUIO.Voucher_ID =無效,1,0)),爲VouchersNotUsed,

我認爲它會去,但可能需要將其更改爲SUM(IF(VUIO.Voucher_ID爲null,1,0))。希望這可以幫助你。

SELECT 
     YEAR(v1.VoucherStarted) as VoucherYear, 
     MONTH(v1.VoucherStarted) as VoucherMonth, 
     COUNT(distinct(v1.ID)) as UniqueVouchers, 
     SUM(IF(v1.OriginalOrderID = O.ID, 1, 0)) as VouchersUsed, 
     SUM(IF(VUIO.Voucher_ID = null, 1, 0)) as VouchersNotUsed, 
     SUM(IF(v1.OriginalOrderID = O.ID, 0, 1)) as TimesVouchersUsed, 

     SUM(IF(O.Created_At >= v1.VoucherStarted AND O.Created_At < v1.Plus1Month), 1, 0) as Month1Cnt, 
     SUM(IF(O.Created_At >= v1.VoucherStarted AND O.Created_At < v1.Plus1Month), VUIO.Amount_Used , 0) as Month1Amt, 

     SUM(IF(O.Created_At >= v1.Plus1Month AND O.Created_At < v1.Plus2Month), 1, 0) as Month2Cnt, 
     SUM(IF(O.Created_At >= v1.Plus1Month AND O.Created_At < v1.Plus2Month), VUIO.Amount_Used , 0) as Month2Amt, 

     SUM(IF(O.Created_At >= v1.Plus2Month AND O.Created_At < v1.Plus3Month), 1, 0) as Month3Cnt, 
     SUM(IF(O.Created_At >= v1.Plus2Month AND O.Created_At < v1.Plus3Month), VUIO.Amount_Used , 0) as Month3Amt, 

     SUM(IF(O.Created_At >= v1.Plus3Month AND O.Created_At < v1.Plus4Month), 1, 0) as Month3Cnt, 
     SUM(IF(O.Created_At >= v1.Plus3Month AND O.Created_At < v1.Plus4Month), VUIO.Amount_Used , 0) as Month3Amt, 

     SUM(IF(O.Created_At >= v1.Plus4Month AND O.Created_At < v1.Plus5Month), 1, 0) as Month4Cnt, 
     SUM(IF(O.Created_At >= v1.Plus4Month AND O.Created_At < v1.Plus5Month), VUIO.Amount_Used , 0) as Month4Amt, 

     SUM(IF(O.Created_At >= v1.Plus5Month AND O.Created_At < v1.Plus6Month), 1, 0) as Month5Cnt, 
     SUM(IF(O.Created_At >= v1.Plus5Month AND O.Created_At < v1.Plus6Month), VUIO.Amount_Used , 0) as Month5Amt, 

     SUM(IF(O.Created_At >= v1.Plus6Month AND O.Created_At < v1.Plus7Month), 1, 0) as Month6Cnt, 
     SUM(IF(O.Created_At >= v1.Plus6Month AND O.Created_At < v1.Plus7Month), VUIO.Amount_Used , 0) as Month6Amt, 

     SUM(IF(O.Created_At >= v1.Plus7Month AND O.Created_At < v1.Plus8Month), 1, 0) as Month7Cnt, 
     SUM(IF(O.Created_At >= v1.Plus7Month AND O.Created_At < v1.Plus8Month), VUIO.Amount_Used , 0) as Month7Amt, 

     SUM(IF(O.Created_At >= v1.Plus8Month AND O.Created_At < v1.Plus9Month), 1, 0) as Month8Cnt, 
     SUM(IF(O.Created_At >= v1.Plus8Month AND O.Created_At < v1.Plus9Month), VUIO.Amount_Used , 0) as Month8Amt, 

     SUM(IF(O.Created_At >= v1.Plus9Month AND O.Created_At < v1.Plus10Month), 1, 0) as Month9Cnt, 
     SUM(IF(O.Created_At >= v1.Plus9Month AND O.Created_At < v1.Plus10Month), VUIO.Amount_Used , 0) as Month9Amt, 

     SUM(IF(O.Created_At >= v1.Plus10Month AND O.Created_At < v1.Plus11Month), 1, 0) as Month10Cnt, 
     SUM(IF(O.Created_At >= v1.Plus10Month AND O.Created_At < v1.Plus11Month), VUIO.Amount_Used , 0) as Month10Amt, 

     SUM(IF(O.Created_At >= v1.Plus11Month AND O.Created_At < v1.Plus12Month), 1, 0) as Month11Cnt, 
     SUM(IF(O.Created_At >= v1.Plus11Month AND O.Created_At < v1.Plus12Month), VUIO.Amount_Used , 0) as Month11Amt, 

     SUM(IF(O.Created_At >= v1.Plus12Month), 1, 0) as Month12Cnt, 
     SUM(IF(O.Created_At >= v1.Plus12Month), VUIO.Amount_Used , 0) as Month12Amt 

    from 
     (SELECT 
       v.id, 
       v.initial_value, 
       v.order_id as OriginalOrderID 
       vo.created_at as VoucherStarted, 
       date_add(vo.created_at, INTERVAL 1 MONTH) as Plus1Month, 
       date_add(vo.created_at, INTERVAL 2 MONTH) as Plus2Month, 
       date_add(vo.created_at, INTERVAL 3 MONTH) as Plus3Month, 
       date_add(vo.created_at, INTERVAL 4 MONTH) as Plus4Month, 
       date_add(vo.created_at, INTERVAL 5 MONTH) as Plus5Month, 
       date_add(vo.created_at, INTERVAL 6 MONTH) as Plus6Month, 
       date_add(vo.created_at, INTERVAL 7 MONTH) as Plus7Month, 
       date_add(vo.created_at, INTERVAL 8 MONTH) as Plus8Month, 
       date_add(vo.created_at, INTERVAL 9 MONTH) as Plus9Month, 
       date_add(vo.created_at, INTERVAL 10 MONTH) as Plus10Month, 
       date_add(vo.created_at, INTERVAL 12 MONTH) as Plus11Month, 
       date_add(vo.created_at, INTERVAL 12 MONTH) as Plus12Month 
      from 
       vouchers v 
       join orders vo 
        ON v.order_id = vo.order_id) V1 

     LEFT JOIN Vouchers_Used_In_Orders VUIO 
     ON V1.ID = VUIO.Voucher_ID 
     AND NOT V1.OriginalOrderID = VUIO.Order_ID 

     LEFT JOIN Orders O 
      ON VUIO.Order_ID = O.ID 
      AND O.Created_At between V1.VoucherStarted and V1.Plus12Month 

    GROUP BY 
     YEAR(v1.VoucherStarted), 
     MONTH(v1.VoucherStarted)