Reputation: 643
I'm trying to select all customers who have at least one purchase in every one of the three months defined by a function called PrevMonth that accepts 2 parameters and returns a string 'YYYY-MM'. First parameter is a date and the second is the number of months to be subtracted from the date in first parameter.
delimiter #
drop function if exists PrevMonth#
CREATE FUNCTION PrevMonth (
in_date DATE
, in_mn_adjust INT)
RETURNS varchar(20)
BEGIN
DECLARE adjusted_date varchar(20);
set in_date := coalesce(in_date, current_date());
set adjusted_date := in_date;
set adjusted_date := date_format(date_sub(adjusted_date, interval in_mn_adjust month), '%Y-%m');
RETURN adjusted_date;
END;
#
And here's my query to select the customers that made at least one purchase each month (I manually counted and there's only one customer)
select DISTINCT oh.cust_id
, concat(cust_name_last,', ',cust_name_first) as 'customer name'
, order_date
from a_bkorders.order_headers oh
join a_bkorders.customers cu on oh.cust_id = cu.cust_id
where Date_format(order_date, '%Y-%m') in (PrevMonth(current_date(), 4))
AND oh.cust_id IN
(
SELECT cust_id
FROM a_bkorders.order_headers
WHERE Date_format(order_date, '%Y-%m') in (PrevMonth(current_date(), 3)))
AND oh.cust_id IN
(
SELECT cust_id
FROM a_bkorders.order_headers oh
WHERE Date_format(order_date, '%Y-%m') in (PrevMonth(current_date(), 2)))
;#
And some strange reason that I can't figure out, it only show me names of customers from the first month (PrevMonth(current_date(), 4)
and that's it. The 'AND's and subqueries didn't work.
Somebody knows why??
Thank you for your help,
Didi
Upvotes: 0
Views: 482
Reputation: 21
EXISTS
is when you need to match the results of query with another
subquery. Query#1 results need to be retrieved where SubQuery results
match. Kind of a Join.
E.g. select customers who have placed orders in month1 and say month2 too,
Whereas IN
is used to retrieve if the value of a specific column
lies in a list (1,2,3,4,5). In this particular case, it would output
all the customers who have a record in at least one of the previous
months not necessarily ALL.
Upvotes: 1
Reputation: 643
OK, after getting stuck for 3 days on the same problem. I've realized that in this case, an intersection (or AND.. IN for MySQL) wouldn't work. So to get the customer that has purchased at least one order in each of the months, I had to use correlated joins with EXISTS. Now, I get one name.
select DISTINCT cust_id, concat(cust_name_last,', ',cust_name_first) as 'customer name'
from a_bkorders.customers
where exists
(select *
from a_bkorders.order_headers
where order_headers.cust_id = customers.cust_id
and date_format(order_date, '%Y-%m') in (PrevMonth( current_date(), 3)))
and exists
(select *
from a_bkorders.order_headers
where order_headers.cust_id = customers.cust_id
and date_format(order_date, '%Y-%m') in (PrevMonth( current_date(), 4)))
and exists
(select *
from a_bkorders.order_headers
where order_headers.cust_id = customers.cust_id
and date_format(order_date, '%Y-%m') in (PrevMonth( current_date(), 2)));
And I get :
VOILA!!!
Upvotes: 1