j'ai une requête dans MySQL qui me sert très bien en obtenant tous les enregistrements dans le mois en cours;
SELECT date_field,val FROM MY_TABLE WHERE date_field>=(CURDATE()-INTERVAL 1 MONTH);
La requête ci-dessus fonctionne bien. donc si ce mois-ci nous n'avions que deux records et 28 jours cela n'apportera que deux records.
date_field | val
========================
2015-02-08 | 567
2015-02-09 | 345
Mais je veux que le nombre d'enregistrements renvoyés soit exactement le même que le nombre de jours du mois en cours. si le mois en cours compte 28 jours et ne comporte que deux enregistrements, il doit apporter;
date_field | val
========================
2015-02-01 | 0
2015-02-02 | 0
2015-02-03 | 0
2015-02-04 | 0
2015-02-05 | 0
2015-02-06 | 0
2015-02-07 | 0
2015-02-08 | 567
2015-02-09 | 345
2015-02-10 | 0
2015-02-11 | 0
2015-02-12 | 0
2015-02-13 | 0
2015-02-14 | 0
2015-02-15 | 0
2015-02-16 | 0
2015-02-17 | 0
2015-02-18 | 0
2015-02-19 | 0
2015-02-20 | 0
2015-02-21 | 0
2015-02-22 | 0
2015-02-23 | 0
2015-02-24 | 0
2015-02-25 | 0
2015-02-26 | 0
2015-02-27 | 0
2015-02-28 | 0
Comment puis-je modifier ma requête pour obtenir le résultat ci-dessus?
Tout d'abord, la condition WHERE date_field >= (CURDATE()-INTERVAL 1 MONTH)
ne limitera pas vos résultats au mois en cours. Il récupérera toutes les dates d'il y a 30 à 31 jours jusqu'à la date actuelle (et à l'avenir, s'il y a des lignes avec des dates futures dans le tableau).
Ça devrait être:
WHERE date_field >= LAST_DAY(CURRENT_DATE) + INTERVAL 1 DAY - INTERVAL 1 MONTH
AND date_field < LAST_DAY(CURRENT_DATE) + INTERVAL 1 DAY
Maintenant, à la question principale, pour créer des dates 28-31, même si la table n'a pas de lignes pour toutes les dates, vous pouvez utiliser une table Calendar
(avec toutes les dates, disons pour les années 1900 à 2200) ou créez-les à la volée, avec quelque chose comme ça (la table days
peut être soit une table temporaire ou vous pouvez même en faire une table dérivée, avec une requête un peu plus compliquée que celle-ci):
CREATE TABLE days
( d INT NOT NULL PRIMARY KEY ) ;
INSERT INTO days
VALUES (0), (1), (2), ....
..., (28), (29), (30) ;
SELECT
cal.my_date AS date_field,
COALESCE(t.val, 0) AS val
FROM
( SELECT
s.start_date + INTERVAL (days.d) DAY AS my_date
FROM
( SELECT LAST_DAY(CURRENT_DATE) + INTERVAL 1 DAY - INTERVAL 1 MONTH
AS start_date,
LAST_DAY(CURRENT_DATE)
AS end_date
) AS s
JOIN days
ON days.d <= DATEDIFF(s.end_date, s.start_date)
) AS cal
LEFT JOIN my_table AS t
ON t.date_field >= cal.my_date
AND t.date_field < cal.my_date + INTERVAL 1 DAY ;
Ce qui précède devrait fonctionner pour tout type de date_field
colonne (date, datetime, horodatage). Si la date_field
la colonne est de type DATE
, la dernière jointure peut être simplifiée pour:
LEFT JOIN my_table AS t
ON t.date_field = cal.my_date ;
Vous pouvez créer un tableau dynamique des dates pour le mois en cours
SELECT date_field
FROM
(
SELECT
MAKEDATE(YEAR(NOW()),1) +
INTERVAL (MONTH(NOW())-1) MONTH +
INTERVAL daynum DAY date_field
FROM
(
SELECT t*10+u daynum
FROM
(SELECT 0 t UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) A,
(SELECT 0 u 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) B
ORDER BY daynum
) AA
) AAA
WHERE MONTH(date_field) = MONTH(NOW());
REMARQUE: si vous coupez et collez la requête ci-dessus telle quelle, elle générera le mois entier pour vous.
Vous avez ensuite GAUCHEZ-LE à votre requête d'origine
SELECT
AAA.date_field,
IFNULL(BBB.val,0) val
FROM
(
SELECT date_field
FROM
(
SELECT MAKEDATE(YEAR(NOW()),1) +
INTERVAL (MONTH(NOW())-1) MONTH +
INTERVAL daynum DAY date_field
FROM
(
SELECT t*10+u daynum FROM
(SELECT 0 t UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) A,
(SELECT 0 u 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) B ORDER BY daynum
) AA
) AA WHERE MONTH(date_field) = MONTH(NOW())
) AAA LEFT JOIN (SELECT date_field,val FROM MY_TABLE) BBB
USING (date_field);
------ Create Exam Table
DECLARE @MyTable TABLE
(date_field DATETIME
,val INT )
INSERT INTO @MyTable
( date_field, val )
VALUES ( CAST('2015-04-05' AS VARCHAR), -- date_field - datetime
270 -- val - int
)
INSERT INTO @MyTable
( date_field, val )
VALUES ( CAST( EOMONTH ( GETDATE() ) AS VARCHAR), -- date_field - datetime
500 -- val - int
)
DECLARE @startDate DATETIME=CAST(MONTH(GETDATE()) AS VARCHAR) + '/' + '01/' + + CAST(YEAR(GETDATE()) AS VARCHAR) -- mm/dd/yyyy
DECLARE @endDate DATETIME= CAST( EOMONTH ( GETDATE() ) AS VARCHAR) -- mm/dd/yyyy
;WITH Calender AS
(
SELECT @startDate AS CalanderDate
UNION ALL
SELECT CalanderDate + 1 FROM Calender
WHERE CalanderDate + 1 <= @endDate
)
SELECT CONVERT(VARCHAR(10),CalanderDate,25) AS [DATE], ISNULL(MT.val,0) val
FROM Calender
LEFT JOIN @MyTable MT ON Calender.CalanderDate = MT.date_field
Vous pouvez utiliser LAST_DAY()
Fonction dans MySQL À la place EOMONTH()
dans [~ # ~] sql [~ # ~]