SQL есть способ сортировать несколько временных столбцов в один, сохраняя метаданные без UNION? - PullRequest
0 голосов
/ 10 ноября 2018

Это расширение моего предыдущего вопроса: SQL существует ли способ сортировки нескольких временных столбцов в один при сохранении метаданных?

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

Итак, подведем итог предыдущему вопросу: У меня есть таблица базы данных SQL, которая имеет четыре столбца с разным временем , которые отсортированы по первой отметке времени (a_time) . Я хочу иметь возможность сортировать их таким образом, чтобы я мог объединить каждую из меток времени a, b, c и d в один столбец, сохранив идентификатор и метаданные.

id | a_time | b_time | c_time | d_time | metadata1 | metadata2
1  | 5      | 7      | 2      | 4      | a         | b
2  | 6      | 1      | 12     | 10     | c         | d
3  | 8      | 9      | 3      | 11     | e         | f

В приведенном выше примере я хотел бы что-то, что приводит к:

id | time | metadata1 | metadata2
2  |  1   |     c     |    d
1  |  2   |     a     |    b
3  |  3   |     e     |    f
1  |  4   |     a     |    b
1  |  5   |     a     |    b
2  |  6   |     c     |    d
1  |  7   |     a     |    b
3  |  8   |     e     |    f
3  |  9   |     e     |    f
2  |  10  |     c     |    d
3  |  11  |     e     |    f
2  |  12  |     c     |    d

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

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Вы, кажется, хотите apply:

select t.id, v.time, t.metadata1, t.metadata2
from t cross apply
     (values (a_time), (b_time), (c_time), (d_time)
     ) v(time)
order by v.time;
0 голосов
/ 10 ноября 2018

Если у вас есть таблица чисел, вы можете получить желаемый результат, JOIN добавив его в таблицу метаданных:

SELECT m.id, n.n, m.metadata1, m.metadata2
FROM numbers n
JOIN metadata m ON m.a_time = n.n OR m.b_time = n.n OR m.c_time = n.n OR m.d_time = n.n
ORDER BY n.n

Выход

id  n   metadata1   metadata2   
2   1   c           d
1   2   a           b
3   3   e           f
1   4   a           b
1   5   a           b
2   6   c           d
1   7   a           b
3   8   e           f
3   9   e           f
2   10  c           d
3   11  e           f
2   12  c           d

Если у вас нет таблицы чисел, вы можете создать ее на лету, используя этот запрос:

SELECT m.id, n.n, m.metadata1, m.metadata2
FROM (SELECT n1.n + n10.n * 10 AS n 
      FROM (SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) n1
           CROSS JOIN
           (SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) n10
           ) n
JOIN metadata m ON m.a_time = n.n OR m.b_time = n.n OR m.c_time = n.n OR m.d_time = n.n
ORDER BY n.n

SQLFiddle

Обновление

Кажется, из соображений производительности лучше добавить предложение WHERE, которое ограничивает диапазон чисел из таблицы numbers диапазоном времени в metadata, т.е.

WHERE n.n <= (SELECT GREATEST(MAX(a_time), MAX(b_time), MAX(c_time), MAX(d_time)) FROM metadata)

Добавление индексов к a_time, b_time, c_time и d_time также повышает производительность этого запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...