sql >> Databáze >  >> RDS >> Mysql

Vyplňování mezer v datech vrácených z databáze – možné čistě SQL řešení?

Ano, je lepší vytvořit tabulku Numbers (jeden sloupec N), která neobsahuje nic jiného než čísla 0 až 999. Lze ji použít pro mnoho věcí, v neposlední řadě pro dotaz jako je níže:

SELECT COUNT(t.click_date) as clicks,
    DATE_FORMAT(adddate($start_date, interval N day), '%d %M %Y') as point 
FROM Numbers
LEFT JOIN tracking t
    ON t.click_date >= adddate($start_date, interval N day)
    and t.click_date < adddate($start_date, interval (N+1) day)
WHERE N between 0 and datediff($start_date, $end_date)
GROUP BY N

Používáte špatný formát. Je to VELKÁ písmena W, nikoli nižší pro den v týdnu, takže '%W %M %Y' nebo '%d %M %Y' pro den v měsíci.http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-format

Používáte GROUP BY DAY(FROM_UNIXTIME(click_date)) poznamenejte si "den" není den v týdnu, ale zobrazujete (nebo se o to pokoušíte) "%W" (pracovní den) – vyberte jeden, nemíchejte je.

UPRAVIT: Pokud nechcete zhmotňovat (nevytvářet jako skutečnou tabulku) sekvenční tabulku čísel, můžete ji sestavit za běhu. Nebude to hezké.

Poznámka:Kombinace N1, N2 a N3 níže poskytuje možný rozsah 0-999

SELECT COUNT(t.click_date) as clicks,
    DATE_FORMAT(adddate($start_date, interval N day), '%d %M %Y') as point 
FROM (
    select N1 * 100 + N2 * 10 + N3 as N
    from (
    select 0 N1 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) N1
    cross join (
    select 0 N2 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) N2
    cross join (
    select 0 N3 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) N3
    ) Numbers
LEFT JOIN tracking t
    ON t.click_date >= adddate($start_date, interval N day)
    and t.click_date < adddate($start_date, interval (N+1) day)
WHERE N between 0 and datediff($start_date, $end_date)
GROUP BY N

ÚPRAVA #2: Přímá tabulka data

Vložte to do nového okna v phpMyAdmin nebo to spusťte jako dávku. Vytvoří tabulku s názvem Data s každým datem ode dne 1900-01-01 (nebo změňte ve skriptu) na 2300-01-01 (nebo změnit).

DROP PROCEDURE IF EXISTS FillDateTable;

delimiter //
CREATE PROCEDURE FillDateTable()
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
  drop table if exists datetable;
  create table datetable (thedate datetime primary key, isweekday smallint);

  SET @x := date('1900-01-01');
  REPEAT 
    insert into datetable (thedate, isweekday) SELECT @x, case when dayofweek(@x) in (1,7) then 0 else 1 end;
    SET @x := date_add(@x, interval 1 day);
    UNTIL @x > date('2300-01-01') END REPEAT;
END//
delimiter ;

CALL FillDateTable;

S takovou obslužnou tabulkou může být váš dotaz jen

SELECT COUNT(t.click_date) as clicks,
    DATE_FORMAT(thedate, '%d %M %Y') as point 
FROM Dates
LEFT JOIN tracking t
    ON t.click_date >= thedate
    and t.click_date < adddate(thedate, interval 1 day)
WHERE thedate between $start_date and $end_date
GROUP BY thedate


  1. Zámek Liquibase - důvody?

  2. Příklad APEX_ZIP

  3. Lomítko nebo žádné lomítko?

  4. 6 způsobů, jak zkontrolovat verzi MariaDB