2012-01-06 2 views
0

나는 내가에 쿼리를 수행하려고 다음과 같은 세 개의 테이블이 있습니다MySQL의 GROUP BY 및 제한 조인

주문

id 

created_at 

상품권을

id 

order_id 

initial_value 

current_value 

바우처 _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에 DISTINCT를 사용할 수 있습니까? 그런 다음

voucher_orders: 
    ID 
    purchase_date 
    value 

:

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

난에 '상품권'과 '주문'을 결합하는 것 (그들은 카운터되지 않도록 문이 null이 될 경우 당신은에서 거짓 조건을 설정해야합니다)

 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; 
,536 'voucher_use'을 가지고

코드에서 '가치 남은'모든 일을하십시오. 이 정보는 저장할 필요가 없습니다.

1

이렇게하면 거의 모든 것을 찾을 수 있습니다. 한 달에 계산 한 것 외에도 그 달에 사용 된 총량을 더했습니다. 먼저 바우처, 초기 날짜 및 귀하의 우려 사항에 따라 12 개월을 더한 쿼리를 시작했습니다. 나는 각각의 "Voucher 당"기준으로 한 달 전에 한 번 사전 계산을하므로 집계를 위해 SUM (IF()) 구문을 단순화하는 데 도움이 될 수 있습니다. 바우처의 단일 계산을 탐지하기 위해 내 사전 설정 (V1)에서 바우처 구입과 관련된 원래 주문을 유지했습니다.그래서 그것을 사용하여 동일한 주문 ID의 SUM (IF())을 수행 할 수 있습니다. 그것의 것이면, VouchersUsed에서 계산됩니다. 바우처 사용 테이블에 대한 왼쪽 조인을 사용하면 해당 테이블이 null로 되돌려지면 인스턴스가 사용되지 않고 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은 이제

합 (IF (VUIO.Voucher_ID = NULL, 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)