MySQL результаты запроса сводки с GROUP BY

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

Чтобы объяснить далее, в настоящее время база данных выглядит следующим образом.

data_id     data_timestamp         data_value    
--------------------------------------------
1           2011-07-07 00:01:00    0.400  
1           2011-07-07 00:02:00    0.500
1           2011-07-07 00:03:00    0.600
1           2011-07-07 00:04:00    0.700
2           2011-07-07 00:01:00    0.100  
2           2011-07-07 00:02:00    0.200
2           2011-07-07 00:03:00    0.250
2           2011-07-07 00:04:00    2.300

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

data_timestamp         input_1    input_2     
--------------------------------------------
2011-07-07 00:01:00    0.400      0.100  
2011-07-07 00:02:00    0.500      0.200
2011-07-07 00:03:00    0.600      0.250
2011-07-07 00:04:00    0.700      2.300

Ниже приведен запрос, который я использую...

SELECT d.data_timestamp, d.input_1, d.input_2
FROM (
    SELECT data_timestamp,
    IF(data_id=1,data_value,NULL) AS 'input_1',
    IF(data_id=2,data_value,NULL) AS 'input_2' FROM data
) AS d ORDER BY data_timestamp ASC

Но это не совсем то, что я хочу, так как теперь есть значения NULL, когда один data_id не имеет значения. Кажется, что GROUP BY также группирует data_value, а это не то, что я хочу.

Какие-либо предложения?

РЕДАКТИРОВАТЬ:

Я уже пытался использовать WHERE d.input_1 IS NOT NULL во внешнем запросе, но не могу получить результаты..

До ГДЕ...

data_timestamp         input_1    input_2     
--------------------------------------------
2011-07-07 00:01:00    0.400      NULL
2011-07-07 00:01:00    NULL       0.100  
2011-07-07 00:02:00    0.500      NULL
2011-07-07 00:02:00    NULL       0.200
2011-07-07 00:03:00    0.600      NULL
2011-07-07 00:03:00    NULL       0.250
2011-07-07 00:04:00    0.700      NULL
2011-07-07 00:04:00    NULL       2.300

Добавление WHERE d.input_1 IS NOT NULL приведет к удалению значений input_2.

data_timestamp         input_1    input_2     
--------------------------------------------
2011-07-07 00:01:00    0.400      NULL
2011-07-07 00:02:00    0.500      NULL
2011-07-07 00:03:00    0.600      NULL
2011-07-07 00:04:00    0.700      NULL

Кроме того, на самом деле, у меня есть около 20 идентификаторов, чтобы сгруппировать их, так что не будет лучшей идеей для ИЛИ или для всех них..

2 ответа

Решение

PIVOTЭто не легко (и не приятно). Я предпочитаю использовать CASE:

SELECT d.data_timestamp
     , SUM( CASE WHEN data_id =  1 THEN data_value ELSE 0 END ) AS 'input_1'
     , SUM( CASE WHEN data_id =  2 THEN data_value ELSE 0 END ) AS 'input_2'
     ...
     , SUM( CASE WHEN data_id = 20 THEN data_value ELSE 0 END ) AS 'input_20'
FROM data 
GROUP BY data_timestamp
ORDER BY data_timestamp ASC

но IF работает и в MySQL:

SELECT d.data_timestamp
     , SUM( IF(data_id =  1, data_value, 0) ) AS 'input_1'
     , SUM( IF(data_id =  2, data_value, 0) ) AS 'input_2'
     ...
     , SUM( IF(data_id = 20, data_value, 0) ) AS 'input_20'
FROM data 
GROUP BY data_timestamp
ORDER BY data_timestamp ASC

Кроме того, вы можете использовать 20-уровневый JOIN:

SELECT d.data_timestamp
     , d01.data_value AS 'input_1'
     , d02.data_value AS 'input_2'
     ...
     , d20.data_value AS 'input_20'
FROM
  ( SELECT DISTINCT d.data_timestamp
    FROM data
  ) AS d 
  LEFT JOIN data AS d01
    ON d01.data_timestamp = d.data_timestamp
    AND d01.data_id =  1
  LEFT JOIN data AS d02
    ON d02.data_timestamp = d.data_timestamp
    AND d02.data_id =  2
  ...                                   --- 20 JOINs
  LEFT JOIN data AS d20
    ON d20.data_timestamp = d.data_timestamp
    AND d20.data_id = 20
ORDER BY d.data_timestamp ASC

Просто присоедините стол к себе!

SELECT dt1.data_timestamp, dt1.input_1, dt2.input_2
FROM data_timestamp dt1
JOIN data_timestamp dt2 
    on dt1.data_timestamp = dt2.data_timestamp 
    and dt2.input_1 is null
WHERE dt1.input_2 is null;

Обратите внимание, что этот запрос предполагает, что значение input_2 присутствует для каждого значения input_1. Если это не тот случай, используйте LEFT JOIN или же CROSS JOIN так далее

Другие вопросы по тегам