2012-01-06 57 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)