Строки SQL-фильтра по перекрытию диапазона

У меня есть таблица снежинок, которая примерно похожа на показанную ниже. Я хочу отфильтровать все строки с одинаковым именем, поставщиком и перекрывающимся диапазоном напряжения.

До:

ИМЯ Поставщик Мин_Вольт Макс_Вольт ОСМО Белл 10 100 ОСМО Белл 80 150 ОСМО Белл 120 155 ОСМО Белл 160 200 МАСД Теле 80 150

После:

ИМЯ Поставщик Мин_Вольт Макс_Вольт ОСМО Белл 160 200 МАСД Теле 80 150

Выполнить только имя и напряжение легко с помощью group by и count() > 1. Но я не знаю, как применить такое сравнение строк друг с другом по отдельности.

Я думал сделать это с помощью оконных функций min/max, таких как

with min_max AS (
SELECT NAME
     , PROVIDER
     , MIN_VOLT
     , MAX_VOLT
     , MAX(max_volt) OVER (PARTITION BY PROVIDER, NAME) AS set_max
     , MIN(min_volt) OVER (PARTITION BY PROVIDER, NAME) AS set_min
FROM Table
)
SELECT NAME, PROVIDER, MIN_VOLT, MAX_VOLT
     FROM min_max
        WHERE MIN_VOLT NOT BETWEEN set_min AND set_min AND MAX_VOLT NOT BETWEEN set_min AND set_max;

Однако это не возвращает строк, поскольку включает строку, которую сравнивают в диапазоне макс/мин. Я не уверен, как заставить его сравнивать каждую строку независимо друг от друга.

Обновлено: Для ясности: строки, которые мы хотим удалить, — это те строки, диапазон напряжения которых перекрывается с другой строкой, имеющей то же ИМЯ и значение ПОСТАВЩИКА. Например, строки 1, 2 и 3 в приведенной выше таблице имеют одно и то же имя и поставщика, а диапазон напряжения перекрывается (10–100, 80–150, 120–155), поэтому их все следует удалить. Принимая во внимание, что строка 4 имеет то же имя и поставщика, но ее диапазон напряжения не пересекается с другими строками, поэтому его следует сохранить.

Как узнать, какую строку оставить?

Charlieface 24.07.2024 17:55

Вы говорите, что удалите верхние 3, поскольку следующая строка min_volt находится внутри приведенной выше, в примере 80 находится между 10 и 100?

Nathan_Sav 24.07.2024 18:04

@Nathan_Sav, да, точно, тогда строка 4 будет сохранена, поскольку ее диапазон не лежит в пределах остальных.

Joseph Lavelle 24.07.2024 18:17

Я добавил более подробную информацию в пост @Charlieface

Joseph Lavelle 24.07.2024 18:17

Я думаю, вам следует добавить еще одну строку к вашим образцам данных, например MASD, Tele, 160, 180, чтобы продемонстрировать, что вы сохраните обе строки для MASD-Tele, поскольку нет перекрытия.

Isolated 24.07.2024 18:44
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
5
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже, LEAD и LAG должны сработать

with min_max AS (
    SELECT
       NAME
     , PROVIDER
     , MIN_VOLT
     , MAX_VOLT
     , LAG(MAX_VOLT) OVER (PARTITION BY PROVIDER, NAME ORDER BY MIN_VOLT, MAX_VOLT) AS prev_max
     , LEAD(MIN_VOLT) OVER (PARTITION BY PROVIDER, NAME ORDER BY MIN_VOLT, MAX_VOLT) AS next_min
    FROM ORENNIA_ANALYTICS_QC.ORENNIA.PRE_PROCESSED_SUBSTATIONS
)
SELECT
    NAME,
    PROVIDER,
    MIN_VOLT,
    MAX_VOLT
FROM min_max
WHERE (prev_max IS NULL OR MIN_VOLT > prev_max)
  AND (next_min IS NULL OR MAX_VOLT < next_min);

db<>рабочий пример

Это отлично работает. Спасибо!

Joseph Lavelle 24.07.2024 21:23

Вы можете попробовать проверить существование

select *
from my_table a
where not exists(select *
                 from my_table b
                 where a.name = b.name and 
                       a.provider = b.provider and
                       a.min_volt <> b.min_volt and 
                       a.max_volt <> b.max_volt and
                       ((a.min_volt between b.min_volt and b.max_volt) or 
                        (a.max_volt between b.min_volt and b.max_volt)));

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