Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Grupuj MySQL według daty i liczby, w tym brakujących dat

Potrzebujesz OUTER JOIN dotrzeć każdego dnia między początkiem a końcem, ponieważ jeśli użyjesz INNER JOIN ograniczy dane wyjściowe tylko do dat, które są połączone (tj. tylko tych dat w tabeli raportu).

Ponadto, gdy używasz OUTER JOIN musisz zadbać o to, aby warunki zawarte w where clause nie powodują implicit inner join; na przykład ORAZ domain_id =1 jeśli użycie w klauzuli WHERE spowoduje pominięcie każdego wiersza, który nie ma tego warunku, ale gdy zostanie użyty jako warunek złączenia, ograniczy tylko wiersze tabeli raportu.

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;

Zmieniłem również tabelę pochodną all_dates, używając DATE_ADD() by przesunąć punkt wyjścia w przyszłość i zmniejszyłem jego rozmiar. Obie te opcje są opcjami i można je dostosować według własnego uznania.

Demo na SQLfiddle

aby uzyskać identyfikator domeny dla każdego wiersza (jak pokazano w twoim pytaniu), musisz użyć czegoś takiego; Zauważ, że możesz użyć IFNULL() który jest specyficzny dla MySQL, ale użyłem COALESCE() który jest bardziej ogólnym SQL. Jednak użycie @parametru, jak pokazano tutaj, jest i tak specyficzne dla MySQL.

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;

Zobacz na SQLfiddle



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tekst w języku bengalskim nie jest wyświetlany w pliku CSV Unicode

  2. WYBIERZ Dane z wielu tabel?

  3. Jak połączyć się z MySQL z wiersza poleceń

  4. Jak {} wpływa na zapytanie MySQL w PHP?

  5. Nie można połączyć się z MySQL za pomocą Sequelize