web-dev-qa-db-fra.com

obtenir toutes les dates du mois en cours

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?

6
indago

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 ;
6
ypercubeᵀᴹ

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);

Essaie !!!

7
RolandoMySQLDBA
------ 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 [~ # ~]

0
user2897607