Сложный оператор SQL SELECT - объединить две строки в два столбца - PullRequest
2 голосов
/ 09 июля 2010

Моя проблема:
У меня есть таблица со столбцами Channel <int> и Value <float>, вместе с отметкой времени и парой других столбцов с дополнительными данными. Channel равно 1 или 2, и есть 1 или 2 строки, в которых есть все, кроме канала, и имеют одинаковое значение.

Что я хотел бы сделать, это выделить эти данные в новую форму, где два канала отображаются в виде столбцов. Я пытался что-то сделать с GROUP BY, но я не мог понять, как получить значения в правильные столбцы на основе канала в той же строке.

Пример:
Для тех из вас, кто предпочитает смотреть на данные, которые у меня есть, и на данные, которые я хочу, и выяснить это оттуда, вот оно. Что у меня есть:

 Channel    Value       Timestamp                OtherStuff
 1          0.2394      2010-07-09 13:00:00      'some other stuff'
 2          1.2348      2010-07-09 13:00:00      'some other stuff'
 1          24.2348     2010-07-09 12:58:00      'some other stuff'
 2          16.3728     2010-07-09 12:58:00      'some other stuff'
 1          12.284      2010-07-09 13:00:00      'unrelated things'
 2          9.6147      2010-07-09 13:00:00      'unrelated things'

Что я хочу:

Value1     Value2      Timestamp                OtherStuff
0.2394     1.2348      2010-07-09 13:00:00      'some other stuff'
24.2348    16.3728     2010-07-09 12:58:00      'some other stuff'
12.284     9.6147      2010-07-09 13:00:00      'unrelated things'

Обновление в ответ на некоторые вопросы, возникшие в комментариях, и несколько последующих вопросов / разъяснений:

  • Да, именно комбинация Timestamp и OtherStuff связывает две строки вместе. (На самом деле OtherStuff - это больше, чем один столбец, но для краткости я упростил.) Есть также пара других столбцов, которые не обязательно равны, но должны быть такими же, как они.

  • Данная таблица уже объединена из двух таблиц, где Value, Channel и Timestamp взяты из одной из них, а остальные (всего 7 дополнительных столбцов, из которых 4 всегда равны для «связанных» строк, а остальные три в основном не совпадают). Было несколько предложений по использованию INNER JOIN - будут ли они работать, если я уже собираюсь вместе (даже если у меня нет myTable, чтобы присоединиться к себе)?

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

  • У меня много данных. Вход поступает от измерительных устройств, расположенных по всей стране, и большинство из них (если не все) загружают результаты измерений (до 4 каналов) каждые 2 минуты. Сейчас у нас в сети около 1000 устройств, так что это означает, что в среднем примерно 1000 строк в минуту. Мне нужно учитывать значения, которые имеют возраст не менее 3, предпочтительно 6 часов, что означает от 180 000 до 360 000 строк в таблице с каналом, значением и отметкой времени.

Ответы [ 3 ]

4 голосов
/ 09 июля 2010

Пока у вас есть что-то, что связывает 2 строки, что-то вроде этого

SELECT
    c1.Value AS Value1, c2.Value AS Value2, c1.timestamp, c2.otherstuff
FROM
    MyTable c1
    JOIN
    MyTable c2 ON c1.timestamp = c2.timestamp AND c1.otherstuff = c2.otherstuff
WHERE
    c1.Channel = 1 AND c2.Channel = 2

Если у вас нет ничего, что связывает 2 строки, то это, вероятно, не может быть сделано, потому что какЗнаете ли вы, что они спарены?

Если у вас есть 1 или 2 строки (отредактируйте: и не знаете, какое у вас значение канала)

SELECT
    c1.Value AS Value1, c2.Value AS Value2, c1.timestamp, c2.otherstuff
FROM
    (
     SELECT Value, timestamp, otherstuff
     FROM MyTable
     WHERE Channel = 1
    ) c1           
    FULL OUTER JOIN
    (
     SELECT Value, timestamp, otherstuff
     FROM MyTable
     WHERE Channel = 2
    ) c2 ON c1.timestamp = c2.timestamp AND c1.otherstuff = c2.otherstuff                  
1 голос
/ 09 июля 2010

Что-то вроде ...

SELECT   MAX(CASE Channel WHEN 1 THEN Value ELSE 0 END) AS Value1,
         MAX(CASE Channel WHEN 2 THEN Value ELSE 0 END) AS Value2,
         Timestamp, 
         OtherStuff
FROM     {tablename}
GROUP BY Timestamp, OtherStuff

(я не проверял это!) (И это предполагает, что ваше значение всегда положительно!)

В качестве альтернативы (см. Комментарии ниже) ...

SELECT   SUM(CASE Channel WHEN 1 THEN Value ELSE 0 END) AS Value1, 
         SUM(CASE Channel WHEN 2 THEN Value ELSE 0 END) AS Value2, 
         Timestamp, 
         OtherStuff 
FROM     {tablename}
GROUP BY Timestamp, OtherStuff
0 голосов
/ 09 июля 2010
SELECT a.Value as Value1, b.Value as Value2,
a.TimeStamp, a.OtherStuff
FROM myTable a INNER JOIN myTable b
ON a.OtherStuff = b.OtherStuff and a.TimeStamp = b.TimeStamp
WHERE a.Channel = 1 AND b.Channel = 2

Написано без редактора запросов. Пожалуйста, будьте добры:)

РЕДАКТИРОВАТЬ: INNER JOIN также может быть использован здесь. EDIT2: исправлено с INNER JOIN. Не спешите понижать голос:)

...