sql >> Database >  >> RDS >> Mysql

MySQL-groep op datum en aantal inclusief ontbrekende datums

Je hebt een OUTER JOIN nodig om elke dag tussen een begin en een einde aan te komen, want als je een INNER JOIN . gebruikt het zal de uitvoer beperken tot alleen de datums die zijn samengevoegd (d.w.z. alleen die datums in de rapporttabel).

Bovendien, wanneer u een OUTER JOIN . gebruikt u moet ervoor zorgen dat de voorwaarden in de where clause veroorzaak geen implicit inner join; bijvoorbeeld AND domain_id =1 als het gebruik in de where-clausule elke rij zou onderdrukken waaraan niet aan die voorwaarde werd voldaan, maar wanneer gebruikt als een join-voorwaarde, beperkt het alleen de rijen van de rapporttabel.

SELECT
      COUNT(r.domain_id)
    , all_dates.Date AS the_date
    , domain_id
FROM (
        SELECT DATE_ADD(curdate(), INTERVAL 2 MONTH) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
        FROM (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
        CROSS JOIN (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
      ) all_dates
      LEFT OUTER JOIN reports r
                  ON all_dates.Date = r.tracked_on
                        AND domain_id = 1
WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
GROUP BY
      the_date
ORDER BY
      the_date ASC;

Ik heb ook de afgeleide tabel all_dates gewijzigd met behulp van DATE_ADD() om het startpunt naar de toekomst te duwen, en ik heb de omvang ervan verkleind. Beide zijn opties en kunnen naar eigen inzicht worden aangepast.

Demo op SQLfiddle

om voor elke rij tot een domain_id te komen (zoals weergegeven in uw vraag), zou u iets als het volgende moeten gebruiken; Merk op dat u IFNULL() . kunt gebruiken wat MySQL-specifiek is, maar ik heb COALESCE() . gebruikt wat meer generieke SQL is. Het gebruik van een @parameter zoals hier getoond is hoe dan ook MySQL-specifiek.

SET @domain := 1;

SELECT
      COUNT(r.domain_id)
    , all_dates.Date AS the_date
    , coalesce(domain_id,@domain) AS domain_id
FROM (
        SELECT DATE_ADD(curdate(), INTERVAL 2 month) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
        FROM (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
        CROSS JOIN (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
      ) all_dates
      LEFT JOIN reports r
                  ON all_dates.Date = r.tracked_on
                        AND domain_id = @domain
WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
GROUP BY
      the_date
ORDER BY
      the_date ASC;

Zie dit op SQLfiddle



  1. Uitvoeringstijd van testquery's in laravel

  2. Hoe dubbele rijen in SQL te elimineren

  3. Een tabel bijwerken in Oracle als een veldwaarde Null is en bepalen of de update succesvol is

  4. Hoe PL/SQL SYS_REFCURSOR in Oracle Database aan te maken?