Перекрестное соединение с наибольшим значением совокупности - PullRequest
0 голосов
/ 12 июня 2019

У меня есть следующая таблица, назовем ее Segments:

-------------------------------------
| SegmentStart | SegmentEnd | Value |
-------------------------------------
| 1            | 4          | 20    |
| 4            | 8          | 60    |
| 8            | 10         | 20    |
| 10           | 1000000    | 0     |
-------------------------------------

Я пытаюсь объединить эту таблицу с собой, чтобы получить следующий набор результатов:

-------------------------------------
| SegmentStart | SegmentEnd | Value |
-------------------------------------
| 1            | 4          | 20    |
| 1            | 8          | 60    |
| 1            | 10         | 60    |
| 1            | 1000000    | 60    |
| 4            | 8          | 60    |
| 4            | 10         | 60    |
| 4            | 1000000    | 60    |
| 8            | 10         | 20    |
| 8            | 1000000    | 20    |
| 10           | 1000000    | 0     |
-------------------------------------

По сути, мне нужно было бы объединить каждую строку со всеми последующими после нее строками, а затем получить MAX() значения между каждой из ранее соединенных строк. Пример: если я соединяю строку 1 со строкой 3, мне потребуется MAX(Value) из всех этих 3 строк.

Я уже выполнил следующий запрос:

SELECT s1.SegmentStart, s2.SegmentEnd, GREATEST(s1.Value, s2.Value) as Value FROM Segments s1 CROSS JOIN Segments s2 ON s1.SegmentStart < s2.SegmentEnd

Этот запрос создает похожую таблицу на желаемую, но поля значений перепутываются следующим образом ( Я отметил между !! строкой, которая отличается ):

-------------------------------------
| SegmentStart | SegmentEnd | Value |
-------------------------------------
| 1            | 4          | 20    |
| 1            | 8          | 60    |
| 1            | 10         | !20!  |
| 1            | 1000000    | !20!  |
| 4            | 8          | 60    |
| 4            | 10         | 60    |
| 4            | 1000000    | 60    |
| 8            | 10         | 20    |
| 8            | 1000000    | 20    |
| 10           | 1000000    | 0     |
-------------------------------------

Проблема связана с функцией GREATEST(), поскольку она сравнивает только две соединяемые строки (начало-конец 1-4, 8-10), а не весь интервал (в этом случае это будет 3 ряда, начинающиеся с 1-4, 4-8, 8-10)

Как мне изменить этот запрос или какой запрос использовать, чтобы получить желаемый результат?

Дополнительная информация, которая может помочь: строки в исходной таблице всегда упорядочиваются по SegmentStart, и не может быть повторяющихся или отсутствующих значений. Каждый интервал между x и y будет отображаться в таблице только один раз, без наложений и вообще без пробелов.

Я использую Maria DB 10.3.13.

1 Ответ

1 голос
/ 12 июня 2019

Как то так?

SELECT
      s1.SegmentStart
    , s2.SegmentEnd
    , MAX(s.Value) as Value 
FROM
    Segments s1
    INNER JOIN Segments s2 ON (
        s2.SegmentEnd > s1.SegmentStart
    )
    INNER JOIN Segments s ON (
            s.SegmentStart >= s1.SegmentStart
        AND s.SegmentEnd <= s2.SegmentEnd
    )
GROUP BY
      s1.SegmentStart
    , s2.SegmentEnd

...