Данные подсчета MySQL за последние 7 дней - PullRequest
3 голосов
/ 17 октября 2010

У меня есть следующая схема.

Таблица голосов

+------------------+--------------+------+-----+---------------------+----------------+
| Field            | Type         | Null | Key | Default             | Extra          |
+------------------+--------------+------+-----+---------------------+----------------+
| id               | int(10)      | NO   | PRI | NULL                | auto_increment |
| aid              | varchar(10)  | NO   |     |                     |                |
| ip               | varchar(100) | NO   |     |                     |                |
| host             | varchar(200) | NO   |     |                     |                |
| timestamp        | varchar(20)  | NO   |     | 0000-00-00 00:00:00 |                |
| user             | tinytext     | NO   |     | NULL                |                |
| userid           | int(10)      | NO   |     | 0                   |                |
+------------------+--------------+------+-----+---------------------+----------------+

Здесь я хочу получить счет каждой помощи за день за последние 7 дней с 0 для дат, когда нет голосов за помощь. метка времени - это метка времени Unix.

Любая помощь высоко ценится.

Ответы [ 2 ]

8 голосов
/ 17 октября 2010

MySQL не имеет рекурсивной функциональности, поэтому вам остается использовать табличный трюк NUMBERS -

  1. Создать таблицу, содержащую только увеличивающиеся числа - это легко сделать с помощью auto_increment:

    DROP TABLE IF EXISTS `example`.`numbers`;
    CREATE TABLE  `example`.`numbers` (
      `id` int(10) unsigned NOT NULL auto_increment,
       PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
  2. Заполните таблицу, используя:

    INSERT INTO NUMBERS
      (id)
    VALUES
      (NULL)
    

    ... столько раз, сколько вам нужно.

  3. Используйте DATE_ADD для построения списка дат, увеличивая дни на основе значения NUMBERS.id.Замените «2010-01-01» и «2010-01-02» на соответствующие даты начала и окончания (но используйте один и тот же формат: ГГГГ-ММ-ДД ЧЧ: ММ: СС).В этом примере я вычел значение NUMBERS.id из CURRENT_DATE, чтобы получить список последовательных значений даты за последнюю неделю -

    SELECT x.dt
      FROM (SELECT DATE_SUB(CURRENT_DATE, INTERVAL (n.id - 1) DAY) AS dt
              FROM numbers n
             WHERE n.id <= 7 ) x
    
  4. LEFT JOIN на таблицу данныхна части даты и времени.

       SELECT x.dt,
               COUNT(v.aid) AS num
         FROM (SELECT DATE_SUB(CURRENT_DATE, INTERVAL (n.id - 1) DAY) AS dt
                 FROM numbers n
                WHERE n.id <= 7 ) x
    LEFT JOIN VOTES v ON DATE(FROM_UNIXTIME(v.timestamp)) = DATE(x.dt)
     GROUP BY x.dt
     ORDER BY x.dt
    

Почему числа, а не даты?

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

Ранее:

  SELECT DATE(FROM_UNIXTIME(v.timestamp)) AS dt,
         COUNT(v.aid)
    FROM VOTES v
   WHERE DATE(FROM_UNIXTIME(v.timestamp)) BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
                                              AND CURRENT_DATE
GROUP BY DATE(FROM_UNIXTIME(v.timestamp))
0 голосов
/ 17 октября 2010

может потребоваться преобразовать ваш varchar (20) в DATETIME, так как это то, что вы используете в любом случае. Но за последние 7 дней просто сделайте ГДЕ отметку времени> @ 7DaysAgo. В своем объяснении вы сказали, что используете метку времени Unix, поэтому вам нужно будет отправить метку времени с этого момента - 7 дней. Вы также захотите изменить значение по умолчанию на 0, так как вы указали временные метки отправки, а не значения DATETIME.

ВЫБЕРИТЕ COUNT (*) в качестве голосов, помогите ИЗ таблицы, ГДЕ отметка времени> @ 7DaysAgo GROUP BY help

...