SQL - Как преобразовать таблицу с диапазоном значений в другую со всеми числами в этом диапазоне? - PullRequest
0 голосов
/ 05 августа 2020

У меня есть таблица (A) с некоторыми интервалами от начальное_значение до конечное_значение с атрибутом для этого диапазона значений.

Мне нужна таблица (B), в которой каждая строка представляет собой число в интервале от start_val до end_val с атрибутом этого диапазона.

Мне нужно сделать что с использованием SQL.

Пример

Таблица A :

+---------+--------+----------+
|start_val| end_val| attribute|
+---------+--------+----------+
| 10      |  12    |  1       |
| 20      |  23    |  2       |
+---------+--------+----------+

Таблица B (Ожидаемый результат):

+---------+----------+
|start_val| attribute|
|end_val  |          |
| interv  |          |
+---------+----------+
| 10      |  1       |
| 11      |  1       |
| 12      |  1       | 
| 20      |  2       |
| 21      |  2       |
| 22      |  2       |
| 23      |  2       |
+---------+----------+

Ответы [ 3 ]

1 голос
/ 05 августа 2020

Вот способ сделать это

select m.start_val + n -1 as start_val_computed
      ,m.attribute
 from t m
 join lateral generate_series(1,(m.end_val-m.start_val)+1) n
   on 1=1

+--------------------+-----------+
| start_val_computed | attribute |
+--------------------+-----------+
|                 10 |         1 |
|                 11 |         1 |
|                 12 |         1 |
|                 20 |         2 |
|                 21 |         2 |
|                 22 |         2 |
|                 23 |         2 |
+--------------------+-----------+

рабочий пример

https://dbfiddle.uk/?rdbms=postgres_12&fiddle=ce9e13765b5a4c3616d95ec659c1dfc9

1 голос
/ 05 августа 2020

Это вариант решения Джорджа, но он немного проще:

select n, m.attribute
from t m cross join lateral
     generate_series(m.start_val, m.end_val) n;

Изменения:

  • CROSS JOIN вместо JOIN. Таким образом, нет необходимости в предложении ON.
  • Нет арифметики c в GENERATE_SERIES().
  • Нет арифметики c в SELECT.
  • Вы можете просто вызвать результат GENERATE_SERIES() с любым именем, которое вы хотите в наборе результатов.

Postgres фактически позволяет вам поместить GENERATE_SERIES() в SELECT:

select generate_series(m.start_val, m.end_val) as n, m.attribute
from t m;

Однако я не сторонник размещения функций генерации строк где-либо, кроме предложения FROM. Мне просто сложно понять, что делает запрос.

1 голос
/ 05 августа 2020

Вы можете использовать подход с календарной таблицей:

SELECT
    t1.val,
    t2.attribute
FROM generate_series(10, 23) AS t1(val)
INNER JOIN TableA t2
    ON t1.val BETWEEN t2.start_val AND t2.end_val
ORDER BY
    t2.attribute,
    t1.val;

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

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