Another way is to use variables to calculate the flag. The variables will store the values of custId
and orderDate
as well as the calculated flag value. All three will be used to calculate the subsequent row's flag.
You will need to sort the rows by custId
, then by orderDate
and implement the following logic to calculate the flag values:
if the current row's custId
is different from the one stored in the corresponding variable (which at this point is carrying the previous custId
), set the flag to false;
otherwise, if the year and month of the current row's orderDate
match those of the date stored in the corresponding variable (which, similarly, is the date from the previous row), keep the previous flag value;
otherwise, set the flag to true if the current orderId
minus one month is the same year and month as the date stored in the variable;
store the current custId
and the year and month of the current orderId
for use in the next iteration.
The MySQL-specific SQL query for that could be something like this:
SELECT
custId,
orderDate,
flag AS hasOrderInPriorMonth
FROM
(
SELECT
@flag :=
CASE
WHEN o.custId <> @custId THEN false
WHEN EXTRACT(YEAR_MONTH FROM o.orderDate) = @orderMonth THEN @flag
ELSE (EXTRACT(YEAR_MONTH FROM o.orderDate - INTERVAL 1 MONTH) = @orderMonth)
END AS flag,
@custId := o.custId as custId,
o.orderDate,
@orderMonth := EXTRACT(YEAR_MONTH FROM o.orderDate)
FROM
(SELECT @custId := '', @orderMonth := 0, @flag := false) as x,
orders as o
ORDER BY
custId ASC,
orderDate ASC
) AS s
;
A demo of this query is available at SQL Fiddle. (It borrows the test setup created by Jehad Keriaki for his own answer.)