I am trying to get top n (2 for now) rows from MySQL (Version: 5.6.29 and 10.1.28-MariaDB). I have seen simple examples on SO or elsewhere (example1,example2) The problem is that my query is more complex and it doesn't seem to be working well.
I have tables as seen on the diagram (some fields are removed for brevity):
Each purchase_item can be either coupon, purchase_offer or subscription_plan (one is valid and the other two are null). Each of these have subscription_days > 0
.
Innermost SELECT works as expected by itself. Second SELECT doesn't work as expected (even if I remove the outer select), purchase_rank
is often the same for the same customer_uuid
as if the innermost select doesn't sort by customer_uuid.
Any ideas? I read that ORDER BY doesn't work well in nested query perhaps that is the problem in my case? How should I do this then? Or maybe query optimizer is doing something weird? I tried replacing CASE with IF and the result it the same. Here is the code:
SELECT
id,
uuid,
purchase_offer,
subscription_plan,
coupon,
customer_uuid,
payment_date,
subscription_days,
FROM
(SELECT
id,
uuid,
purchase_offer,
subscription_plan,
coupon,
customer_uuid,
payment_date,
subscription_days,
@purchase_rank := CASE @current_customer
WHEN customer_uuid THEN @purchase_rank + 1
ELSE 1
END AS purchase_rank,
@current_customer:= customer_uuid AS current_customer
FROM
(SELECT
pi.id,
pi.uuid,
pi.purchase_offer,
pi.subscription_plan,
pi.coupon,
pi.customer_uuid,
p.payment_date,
IFNULL(po.subscription_days, IFNULL(sp.subscription_days, cpo.subscription_days)) AS subscription_days
FROM
purchase_item pi
JOIN purchase p ON p.id = pi.purchase
LEFT JOIN purchase_offer po ON pi.purchase_offer = po.id
LEFT JOIN subscription_plan sp ON pi.subscription_plan = sp.id
LEFT JOIN coupon cp ON pi.coupon = cp.id
LEFT JOIN purchase_offer cpo ON cp.purchase_offer = cpo.id
WHERE
p.status = 'COMPLETED'
AND pi.customer_uuid IS NOT NULL
AND p.payment_date IS NOT NULL
AND (po.subscription_days > 0
OR sp.subscription_days > 0
OR cpo.subscription_days > 0)
ORDER BY pi.customer_uuid , p.payment_date DESC) AS temp)
AS pu
WHERE
pu.purchase_rank <= 2
ORDER BY pu.customer_uuid , pu.payment_date DESC
Any help would be greatly appreciated. Thanks in advance.