Reputation: 20045
I observed this skipping rows for this type of expression quite a few times and always wondered whether this is a bug or if it makes sense - at least technically. The purpose of the queries is to generate sequential table content. Mostly DATEs or DATETIMEs.
t
is just any table with at least 30 rows.
This version produces the result as intended:
set @date = "2012-01-01";
select
@date := date_add(@date, interval 1 day) as d
from t
#having d < "2012-01-31"
limit 30
;
output:
'2012-01-02'
'2012-01-03'
'2012-01-04'
...
'2012-01-31'
now including the HAVING condition (so I don't have to use a number to limit how many rows I want to generate, but can simply specify an upper boudary):
set @date = "2012-01-01";
select
@date := date_add(@date, interval 1 day) as d
from t
having d < "2012-01-31"
limit 30
;
output:
'2012-01-03'
'2012-01-05'
'2012-01-07'
...
'2012-01-29'
'2012-01-31'
But please mind - this is a WHY-question - not a HOW-question.
Upvotes: 1
Views: 806
Reputation: 35907
The problem is that when you call the column d
in your HAVING
clause, it computes the expression @date := date_add(@date, interval 1 day)
again. This means that interval 1 day
is added twice to the initial @date
variable, thus why you have gaps in your entries. You can verify this fact by adding an extra condition, for instance HAVING d < '2012-01-31' AND d > '2012-01-01'
.
The correct query would be as follow :
SET @date = '2012-01-01';
SELECT @date := date_add(@date, interval 1 day) as d
FROM t
WHERE date_add(@date, interval 1 day) < '2012-01-31'
ORDER BY d
LIMIT 30;
Note that a HAVING
clause should be used with aggregate functions, and that using LIMIT without an ORDER BY
clause might give you results in an incorrect order.
Upvotes: 2