Как получить значения за каждый день в месяце - PullRequest
6 голосов
/ 16 февраля 2010

Данные:

values date
14 1.1.2010
20 1.1.2010
10 2.1.2010
7  4.1.2010
...

образец запроса о январе 2010 года должен получить 31 строку. Один на каждый день. И ценности должны быть добавлены. Прямо сейчас я мог бы сделать это с 31 запросом, но я хотел бы, чтобы это работало с одним. Возможно ли это?

Результаты:

1. 34
2. 10
3.  0
4.  7
...

Ответы [ 5 ]

11 голосов
/ 16 февраля 2010

Это на самом деле удивительно сложно сделать в SQL. Один из способов сделать это - использовать длинный оператор select с UNION ALLs для генерации чисел от 1 до 31. Это демонстрирует принцип, но я остановился на 4 для ясности:

SELECT MonthDate.Date, COALESCE(SUM(`values`), 0) AS Total
FROM (
    SELECT 1 AS Date UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 4 UNION ALL
    --
    SELECT 28 UNION ALL
    SELECT 29 UNION ALL
    SELECT 30 UNION ALL
    SELECT 31) AS MonthDate
LEFT JOIN Table1 AS T1
ON MonthDate.Date = DAY(T1.Date)
AND MONTH(T1.Date) = 1 AND YEAR(T1.Date) = 2010
WHERE MonthDate.Date <= DAY(LAST_DAY('2010-01-01'))
GROUP BY MonthDate.Date

Возможно, было бы лучше использовать таблицу для хранения этих значений и присоединиться к ней.

Результат:

1, 34
2, 10
3, 0
4, 7
5 голосов
/ 16 февраля 2010

Учитывая, что для некоторых дат у вас нет данных, вам необходимо заполнить пробелы. Один из подходов к этому - предварительно заполнить таблицу календаря всеми нужными вам датами и присоединиться к ней. Если вы хотите, чтобы в результатах отображались номера дней, которые вы указали в своем вопросе, вы можете заранее заполнить их в своем календаре в виде меток.

Вы бы присоединили свое поле даты таблицы данных к полю даты таблицы календаря, сгруппировав по этому полю и суммируя значения. Возможно, вы захотите указать пределы для диапазона охватываемых дат.

Так что вы можете иметь:

CREATE TABLE Calendar (
    label varchar,
    cal_date date,
    primary key ( cal_date )
)

Запрос:

SELECT
    c.label,
    SUM( d.values )
FROM
    Calendar c
JOIN
    Data_table d
ON  d.date_field = c.cal_date
WHERE
    c.cal_date BETWEEN '2010-01-01' AND '2010-01-31'
GROUP BY
    d.date_field
ORDER BY
    d.date_field

Обновление

Я вижу, у вас есть даты, а не даты. Вы можете просто использовать функцию MySQL DATE () в соединении, но это, вероятно, не будет оптимальным. Другой подход заключается в том, чтобы в таблице календаря было указано время начала и окончания, определяющее «интервал времени» для каждого дня.

1 голос
/ 01 августа 2017

Это работает для меня ... Это модификация запроса, который я нашел на другом сайте. Предложение «ИНТЕРВАЛ 1 МЕСЯЦ» гарантирует, что я получу данные текущего месяца, включая нули для дней, в которых нет обращений. Измените это значение на «ИНТЕРВАЛ 2 МЕСЯЦА», чтобы получить данные за последние месяцы и т. Д.

У меня есть таблица с именем «полезная нагрузка» со столбцом «отметка времени». Затем я соединяю столбец отметки времени с динамически генерируемыми датами, приводя его так, чтобы даты соответствовали предложению ON.


SELECT `calendarday`,COUNT(P.`timestamp`) AS `cnt` FROM 
(SELECT @tmpdate := DATE_ADD(@tmpdate, INTERVAL 1 DAY) `calendarday`
    FROM (SELECT @tmpdate := 
        LAST_DAY(DATE_SUB(CURDATE(),INTERVAL 1 MONTH))) 
        AS `dynamic`, `payload`) AS `calendar`
LEFT JOIN `payload` P ON DATE(P.`timestamp`) = `calendarday`
GROUP BY `calendarday`
1 голос
/ 01 мая 2015

Чтобы динамически получить даты в диапазоне дат с помощью SQL, вы можете сделать это (пример в mysql):

Создать таблицу для хранения чисел от 0 до 9.

CREATE TABLE ints ( i tinyint(4) );

insert into ints (i)
values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

Запустите запрос так:

select ((curdate() - interval 2 year) + interval (t.i * 100 + u.i * 10 + v.i) day) AS Date
from
    ints t
    join ints u
    join ints v
having Date between '2015-01-01' and '2015-05-01'
order by t.i, u.i, v.i

Будет сгенерировано все даты в период с 1 января 2015 г. по 1 мая 2015 г.

Output
2015-01-01
2015-01-02
2015-01-03
2015-01-04
2015-01-05
2015-01-06
...
2015-05-01

Запрос присоединяется к таблице ints 3 раза и получает инкрементное число (от 0 до 999). Затем он добавляет это число как дневной интервал, начинающийся с определенной даты, в данном случае это дата 2 года назад. Любой диапазон дат от 2 лет назад и до 1000 дней вперед может быть получен с примером выше. Чтобы сгенерировать запрос, который генерирует даты для более чем 1000 дней, просто присоединитесь к таблице значений еще раз, чтобы обеспечить диапазон до 10 000 дней и т. Д.

0 голосов
/ 16 февраля 2010

Если я правильно понимаю довольно расплывчатый вопрос, вы хотите знать количество записей для каждой даты в течение месяца. Если это правда, вот как вы можете это сделать:

SELECT COUNT(value_column) FROM table WHERE date_column LIKE '2010-01-%' GROUP BY date_column
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...