2016-09-01 1 views
1

Я не уверен, что эта структура данных способна сделать результат, который я хочу. http://sqlfiddle.com/#!9/84939mysql отображает каждый тип в строке и группе по дате

Это данные, пожалуйста, игнорируйте столбец продолжительности.

+----+---------------------+---------------------+---------------------+----------+--------+------+ 
| id | created_date  | start_date   | end_date   | duration | status | type | 
+----+---------------------+---------------------+---------------------+----------+--------+------+ 
| 1 | 2016-04-05 15:23:29 | 2016-08-15 10:21:53 | 2016-08-19 00:00:00 |  30 |  1 | 2 | 
| 2 | 2016-04-06 15:23:29 | 2016-08-15 10:21:53 | 2016-08-19 00:00:00 |  30 |  1 | 1 | 
| 3 | 2016-04-06 15:23:29 | 2016-08-15 10:21:53 | 2016-08-19 00:00:00 |  30 |  1 | 3 | 
| 4 | 2016-04-06 15:23:29 | 2016-08-17 10:21:53 | 2016-08-19 00:00:00 |  30 |  1 | 1 | 
| 5 | 2016-04-06 15:23:29 | 2016-08-17 09:21:53 | 2016-08-19 00:00:00 |  30 |  1 | 1 | 
| 6 | 2016-04-06 15:23:29 | 2016-08-01 09:21:53 | 2016-08-31 00:00:00 |  30 |  1 | 1 | 
| 7 | 2016-04-06 15:23:29 | 2016-08-01 09:21:53 | 2016-08-31 00:00:00 |  30 |  0 | 1 | 
| 8 | 2016-04-06 15:23:29 | 2016-08-15 09:21:53 | 2016-08-16 00:00:00 |  30 |  1 | 2 | 
| 9 | 2016-04-06 15:23:29 | 2016-08-16 09:21:53 | 2016-08-17 00:00:00 |  30 |  1 | 3 | 
| 10 | 2016-04-06 15:23:29 | 2016-08-19 09:21:53 | 2016-08-20 00:00:00 |  30 |  1 | 2 | 
+----+---------------------+---------------------+---------------------+----------+--------+------+ 

Я хочу отфильтровать отчет с 2016-08-15 до 2016-08-19. для 2015-08-19 даже 00:00:00, я не уверен, считаю счет или нет. Но для моего примера. Я просто считаю, потому что он находится в диапазоне. Это резюме сделано мной вручную: -

(type-2)15,16,17,18,19 
(type-1)15,16,17,18,19 
(type-3)15,16,17,18,19 
(type-1)17,18,19 
(type-1)17,18,19 
(type-1)15,16,17,18,19 
(type-1)15,16,17,18,19 
(type-2)15,16 
(type-3)16,17 
(type-2)19,20 

Это результат я хотел бы генерировать в данных SQL возвращения.

+------------+--------+-----------+-----------+-----------+ 
| date  | ct_all | ct_type_1 | ct_type_2 | ct_type_3 | 
+------------+--------+-----------+-----------+-----------+ 
| 2016-08-15 | 6  | 3   | 2   | 1   | 
| 2016-08-16 | 7  | 3   | 2   | 2   | 
| 2016-08-17 | 8  | 5   | 1   | 2   | 
| 2016-08-18 | 7  | 5   | 1   | 1   | 
| 2016-08-19 | 8  | 5   | 2   | 1   | 
+------------+--------+-----------+-----------+-----------+ 

ct_all = посчитать все

ct_type_1 = Count общей для 1-го типа

до тех пор, как тип попадают в датой_начала и end_date тогда он будет рассчитывать. Обычно мы выполнили поиск по дате базы на один тип столбца, например created_date. и я могу использовать между> = и < =, чтобы найти диапазон. Но у этого была дата начала и окончания. Не уверен, что это возможно или нет.

+0

У вас должна быть таблица со всеми существующими датами (см., Например, [Таблицы календаря: Бесценный инструмент базы данных] (http://www.brianshowalter.com/calendar_tables)). Соедините это с вашими данными о '> = start_date' и' <= end_date'. Это можно просто подсчитать. – Solarflare

ответ

2

У вас здесь три разных вещи.

  1. перечисление дней.
  2. a DATETIME диапазон фильтр.
  3. так называемый поворот, поворот строк по типу в столбцы.

Полезно принимать эти данные за один раз.

Во-первых, я думаю, у вас есть пять дней, которые вы хотите отфильтровать, [15 августа 2016 года - 19 августа 2016 года] включительно. Вы хотите составить список всех этих дней. Этот маленький запрос сделает это. (http://sqlfiddle.com/#!9/84939/21/0)

SELECT CONVERT('2016-08-15' + INTERVAL seq DAY, DATETIME) AS CURDATE 
     FROM (SELECT 0 AS SEQ UNION ALL SELECT 1 UNION ALL SELECT 2 
           UNION ALL SELECT 3 UNION ALL SELECT 4 
      ) seq_0_to_4 

(Обратите внимание, что-то:. MariaDB fork of MySQL имеет sequence tables like seq_0_to_4 built in, так что вы не должны делать все эти UNION ALL материала)

Во-вторых, вы хотите получить список type значений, возникающий на ежедневно. Вы можете добиться, чтобы это произошло с LEFT JOIN, так (http://sqlfiddle.com/#!9/84939/26/0).

SELECT seq.curdate, record.type 
    FROM (

      SELECT CONVERT('2016-08-15' + INTERVAL seq DAY, DATETIME) AS CURDATE 
      FROM (SELECT 0 AS SEQ UNION ALL SELECT 1 UNION ALL SELECT 2 
            UNION ALL SELECT 3 UNION ALL SELECT 4 
       ) seq_0_to_4 
     ) seq 
    LEFT JOIN record ON seq.curdate >= DATE(record.start_date) 
        AND seq.curdate <= DATE(record.end_date) 

Это дает вам список curdate и type значений.

Условие этого соединения выбирает record строк, начинающихся до или перед каждой датой, и заканчивается в любое время на каждой дате.

И, наконец, вам нужно выполнить операцию pivot, чтобы суммировать подсчеты значений типа. Это выглядит примерно так.(http://sqlfiddle.com/#!9/84939/28/0)

SELECT curdate, 
     COUNT(type) ct_all, 
     SUM(CASE WHEN type = 1 THEN 1 ELSE 0 END) ct_1, 
     SUM(CASE WHEN type = 2 THEN 1 ELSE 0 END) ct_2, 
     SUM(CASE WHEN type = 3 THEN 1 ELSE 0 END) ct_3 
    FROM (the above query) d 
    GROUP BY curdate 
    ORDER BY curdate 

Это тот случай, когда структурированная часть Structured Query Language необходимо.

+0

Я не могу себе представить, что это можно сделать. seq_0_to_4 что-то новое Я узнаю из знаний mysql. Спасибо Олли Джонсу! Удивительное объяснение от вас! Оценил! – Shiro