SELECT d.x, count(DISTICT t.email) as y
That means "show me the field name x in table d, and the count of the different values kept in field email in table t. When you show me that email count, give the column the name “y”
FROM (everything till the GROUP BY is part of this first FROM)
(SELECT
min_date + INTERVAL number month as x
FROM
(SELECT ('2012-10-01') AS min_date, DATE('2014-11-04' AS max_date) as m
CROSS JOIN tbl_numbers
WHERE min_date+INTERVAL number month <= max_date) as d
This is a bit more complex because your table d is really a subquery… that includes another subquery in its FROM to create table named (or with alias of) d
So basically, your table d is created by creating two fields that do not really select values, these values are already give. These fields will have the names of min_date and max_date.
The whole subquery will have a name (alias) or m. It doesn’t need a FROM clause because I’m not really selecting any real field, just putting the values myself there.
CROSS JOIN tbl_numbers
WHERE min_date + INTERVAL number month <= max_date) AS d
LEFT OUTER JOIN `tbl_statistics` AS t
ON t.logdate BETWEEN d.x
AND d.x + INTERVAL 1 month
Now, this ficticious table m will CROSS JOIN (or will do the cartesian product which is what CROSS JOIN means) with the table named tbl_numbers but will only be a valid output if when I add months to the min_date is still less or equal than the max_date.
numbers is just a field.
And all this whole thing is our table named as d
It is very typical to give aliases to tables (real or not). Some tables have really long names so giving it an alias of just one or two characters helps to write less.
In this case.
Now, our table d is joined with table tbl_statistics (alias as t, so when I refer to the name of the fields I don’t have to write the whole table name ;)) with a LEFT OUTER JOIN
That means that all the records of table d (the left part, because it comes first in the FROM) will be included in the result, but from table t (real name tbl_statistics), the only records included will be those that share the same values using the field t.logdate
Still, not all values will be shown because t.logdate value also has the condition of being between the value of the field x (coming from table t) and x + 1 month
GROUP BY means that the result (which will be only two fields, x and y, selected at the very beginning of the query) that for each different value of field x, show me the count number of emails (field y)
Not sure if this is clear