我正在尝试对以下三个表执行查询:
订单
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个月。< / p>
这是我到目前为止所做的:
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)
如果购买的优惠券未被使用,则会对其进行正确计数,但一旦开始使用,外部联接会导致优惠券被多次计算。此外,当我只想第一次使用时,它会计算凭证的每次使用。
有人可以帮忙吗?
任何建议表示赞赏。
感谢。
答案 0 :(得分:1)
您可以在优惠券ID上使用COUNT DISTINCT吗? (您需要将if语句中的false条件设置为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)
答案 1 :(得分:1)
这应该会给你几乎所有你想要的东西。除了每月的计数外,我还添加了每个月使用的总金额。我首先开始查询以获得凭证,其初始日期以及每个您关注的12个月。我在每个“每个凭证”的基础上预先计算了一个月,因此它可以帮助简化聚合的SUM(IF())结构。为了检测单张凭证,在我的预查询(V1)中, 我保留了与购买优惠券相关的原始订单。因此,通过使用它,我可以执行相同订单ID的SUM(IF())。如果是那个,它会在VouchersUsed中计算。左边连接到凭证使用表,如果返回为空,则没有使用它的实例,并且将是NULL值。
您会注意到,我还采取了预防措施,以防止通过LEFT JOIN包含原始订单,明确阻止用于购买凭证的订单ID被计算并错误地丢弃计数。
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 = null,1,0))as 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 )
答案 2 :(得分: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;
在代码中完成所有'剩余价值'的东西。此信息无需存储。