Question :
Formulate the question was a bit difficult, but I’ll try to be as explicit as possible using an example to set the question straight.
There are the following data in my table:
Thepurposeistoexecuteaquerysql
(theDBMSusedisMySQL)inthedaterangebetween2014-09-01until2014-09-10andhavethefollowingresult:
What I already have:
To be honest, I have a lot of no idea how to do this, so far I have solved this in the control of my application, an algorithm like:
between
of the desired dates and save to a list; Calendar
in Java); Is there any way to do this already in the query in sql
? The way I do now is not the most efficient.
Answer :
You can use a generator for no intermediate tables: / p>
SELECT
DATE_ADD( '2014-01-01', INTERVAL d1+d2*10+d3*100 DAY ) AS diaDoAno
FROM
( SELECT 0 AS d1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t1,
( SELECT 0 AS d2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t2,
( SELECT 0 AS d3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 ) t3
WHERE
YEAR( DATE_ADD( '2014-01-01', INTERVAL d1+d2*10+d3*100 DAY ) ) = 2014
The query looks great, but the performance is excellent.
Operation:
d1+d2*10+d3*100
transforms the outputs of the 3 subqueries into a number of 0
to 399
DATE_ADD( '2014-01-01', INTERVAL d1+d2*10+d3*100 DAY )
we’ve turned this number into a date. How to use:
As described in other answers, just use JOIN
with the desired table.
SELECT
DATE_ADD( '2014-01-01', INTERVAL d1+d2*10+d3*100 DAY ) AS dia_do_ano.
contador,
quantidade
FROM
( SELECT 0 AS d1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t1,
( SELECT 0 AS d2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) t2,
( SELECT 0 AS d3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 ) t3
LEFT JOIN
sua_tabela ON dia_do_ano = data_tempo
WHERE
YEAR( DATE_ADD( '2014-01-01', INTERVAL d1+d2*10+d3*100 DAY ) ) = 2014
Cold.
As the Wakin suggested and as I was writing.
Make a date table, and from there a LEFT JOIN
with your table.
Here are two links to suggestions for creating this table:
For null
values, just add COUNT
to your IFNULL()
and your problem will be solved.
You can create a PROCEDURE by creating a temporary table before running the query, for example:
DELIMITER //
CREATE PROCEDURE TempDateTable(data_ini DATE, data_fim DATE)
BEGIN
DECLARE v_curdate DATE;
SET @v_curdate = data_ini;
START TRANSACTION;
DROP TABLE IF EXISTS tempdatetable;
CREATE TEMPORARY TABLE tempdatetable (
data_tempo DATE NOT NULL PRIMARY KEY
);
WHILE @v_curdate <= data_fim DO
INSERT INTO 'TempDateTable'('data_tempo') VALUES (@v_curdate);
SET @v_curdate = ADDDATE(@v_curdate, INTERVAL 1 DAY);
END WHILE;
COMMIT;
END//
DELIMITER ;
Data
--------------------------------------
| data_tempo | contador | quantidade |
--------------------------------------
| 2014-09-01 | CDR_SUC | 256 |
| 2014-09-04 | CDR_SUC | 258 |
| 2014-09-05 | CDR_SUC | 195 |
| 2014-09-06 | CDR_SUC | 100 |
| 2014-09-10 | CDR_SUC | 317 |
--------------------------------------
Running Procedure
CALL 'databasetest'.'TempDateTable'('2014-09-01', '2014-09-10');
Conducting the query
SELECT tmp.data_tempo, test.contador, IFNULL(test.quantidade,0)
FROM tempdatetable as tmp
LEFT JOIN testedados as test ON DATE(test.data_tempo) = DATE(tmp.data_tempo);
Result:
--------------------------------------
| data_tempo | contador | quantidade |
--------------------------------------
| 2014-09-01 | CDR_SUC | 256 |
| 2014-09-02 | NULL | 0 |
| 2014-09-03 | NULL | 0 |
| 2014-09-04 | CDR_SUC | 258 |
| 2014-09-05 | CDR_SUC | 195 |
| 2014-09-06 | CDR_SUC | 100 |
| 2014-09-07 | NULL | 0 |
| 2014-09-08 | NULL | 0 |
| 2014-09-09 | NULL | 0 |
| 2014-09-10 | CDR_SUC | 317 |
--------------------------------------