Reputation: 3
I'm trying to write a query on MySQL workbench that shows me when a customer last ordered from my client's website. I'm using two tables for this purpose. One is called "orders", which is updated with order time whenever a new order is placed and assigns a unique id to each new order. The other table is called "orders_customers_details", which is also updated whenever a new order is placed and contains the unique id (based on a combination of customer's email address and phone number) of the customer placing the order, as well as a key which corresponds to the orders table's id.
My problem is that the query I'm using is not returning every customer's most recent order. In the case of some customers, I'm being given the date of their fourth or fifth most recent order.
I'm left joining orders on orders_customer_details:
left join orders o
on ocd.id = o.customer_details_id
I've also tried using a left outer join, and the following join:
from orders o, orders_customers_details ocd
where o.customer_details_id = ocd.id
In order to retrieve the most recent order only, I'm grouping by customer_id HAVING max(order.id). FYI, order.id increases with the placement of each new order, so the order with the highest id is the most recent order.
I've also tried
SELECT customer_id, MAX(order.id)
and then grouped by customer_id, but to no avail.
Here's the entire code:
select customer_id, o.id as id_of_last_order, date(order_date) as
last_ordered, timestampdiff(day, order_date, now()) as
days_since_last_ordered
from orders o, orders_customers_details ocd
where o.customer_details_id = ocd.id
group by customer_id having max(o.id)
order by customer_id;
Upvotes: 0
Views: 41
Reputation: 1270593
A typical method in MySQL is to use a correlated subquery to get the most recent order:
select ocd.customer_id, o.id as id_of_last_order,
date(o.order_date) as last_ordered,
timestampdiff(day, o.order_date, now()) as days_since_last_ordered
from orders o join
orders_customers_details ocd
on o.customer_details_id = ocd.id
where o.order_date = (select max(o2.order_date)
from orders o2 join
orders_customers_details ocd2
on o2.customer_details_id = ocd2.id
where oc2.customer_id = ocd.customer_id
)
order by ocd.customer_id;
Of course, if o.id
is an auto-incrementing column, then the largest value is from the most recent date. If this is the case, then you can just use aggregation:
select ocd.customer_id,
max(o.id) as id_of_last_order,
date(max(o.order_date)) as last_ordered,
timestampdiff(day, max(o.order_date), now()) as days_since_last_ordered
from orders o join
orders_customers_details ocd
on o.customer_details_id = ocd.id
group by ocd.customer_id
order by ocd.customer_id;
In MySQL 8+, you would simply use window functions:
select *
from (select ocd.customer_id, o.id as id_of_last_order,
date(o.order_date) as last_ordered,
timestampdiff(day, o.order_date, now()) as days_since_last_ordered,
row_number() over (partition by ocd.customer_id order by o.order_date desc) as seqnum
from orders o join
orders_customers_details ocd
on o.customer_details_id = ocd.id
) ocd
where seqnum = 1
order by ocd.customer_id;
Upvotes: 1
Reputation: 16908
Try this-
SELECT
customer_details_id customer_id,
MAX(o.id) AS id_of_last_order,
MAX(order_date) AS last_ordered,
TIMESTAMPDIFF(DAY, MAX(order_date), NOW()) AS days_since_last_ordered
FROM orders O
INNER JOIN orders_customers_details OCD
ON O.customer_details_id = OCD.id
GROUP BY customer_details_id
ORDER BY customer_details_id;
Upvotes: 0
Reputation: 17655
Using a correlated sub query in the where clause to find the most recent order by customer and tidying up the code then something like this
select customer_id, o.id as id_of_last_order, date(order_date) as last_ordered,
timestampdiff(day, order_date, now()) as days_since_last_ordered
from orders_customers_details ocd
join orders o on o.customer_details_id = ocd.id
where ocd_id = (select max(ocd_id) from orders_customers_details ocd1 where ocd1.customer_id = ocd_customer_id);
Though I cannot be certain without table definitions sample data etc..
Upvotes: 0