Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL група по дата и брой, включително липсващи дати

Нуждаете се от OUTER JOIN за да стигнете до всеки ден между началото и края, защото ако използвате INNER JOIN той ще ограничи изхода само до датите, които са обединени (т.е. само тези дати в таблицата на отчета).

Освен това, когато използвате OUTER JOIN трябва да се погрижите за условията в where clause не предизвикват implicit inner join; например И domain_id =1 ако използването в клаузата where би потиснало всеки ред, който не е отговарял на това условие, но когато се използва като условие за присъединяване, ограничава само редовете на таблицата на отчета.

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;

Също така промених таблицата, извлечена от all_dates, като използвах DATE_ADD() за да избутам отправната точка в бъдещето и намалих нейния размер. И двете са опции и могат да бъдат коригирани, както сметнете за добре.

Демо в SQLfiddle

за да стигнете до domain_id за всеки ред (както е показано във вашия въпрос), ще трябва да използвате нещо като следното; Имайте предвид, че можете да използвате IFNULL() което е специфично за MySQL, но съм използвал COALESCE() който е по-общ SQL. Въпреки това използването на @параметър, както е показано тук, така или иначе е специфично за 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;

Вижте това в 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. Използвайте LIKE %..% със стойности на полета в MySQL

  2. Синтаксис на SQL UPDATE – Изброен от СУБД

  3. Синтактична грешка в Mysqli UPDATE SET WHERE

  4. Как лесно да определя възрастта от рожден ден? (php)

  5. python:как да получавам известия за промени в базата данни на mysql?