Как эффективно фильтровать повторяющиеся значения s и d из таблицы пар (s, d), сохраняя только самые маленькие пары (s, d)

0

Вот мой тестовый пример

CREATE TABLE matches AS
        SELECT 1 s, 2 d
  UNION SELECT 1, 3 -- (1,2) preferred
  UNION SELECT 2, 2 -- (1,2) preferred
  UNION SELECT 2, 3
  UNION SELECT 3, 3 -- (2,3) preferred
  UNION SELECT 3, 4;

Я хочу отфильтровать эту таблицу и сохранить каждое значение s или d только один раз, задавая приоритеты наименьшим (s, d) парам. Результат должен быть (1,2),(2,3),(3,4). Как это сделать эффективно?

Я попробовал запрос ниже, но он работает только в том случае, если значения d, связанные с разными значениями s, не перекрываются

SELECT * FROM (
   SELECT
     *,
     row_number() OVER (PARTITION BY s ORDER BY d) rs,
     row_number() OVER (PARTITION BY d ORDER BY s) rd
    FROM matches
   ) t
WHERE rd = rs;

Любая помощь будет очень высоко ценится.

  • 2
    Вы используете MySQL или MS SQL Server?
  • 0
    Пожалуйста, не используйте теги, которые не относятся к вашему вопросу. Я удалил теги базы данных, так как неясно, какой из них вы на самом деле используете. Пожалуйста, добавьте тег только той базы данных, которую вы фактически используете
Показать ещё 5 комментариев
Теги:
join

1 ответ

0

Если я правильно интерпретирую ваши намерения, вы можете сделать это, скопировав таблицу в новую (возможно временную) таблицу с индексами UNIQUE на s и d и используя INSERT IGNORE для копирования данных:

CREATE TABLE matches AS
        SELECT 1 s, 2 d
  UNION SELECT 1, 3 -- (1,2) preferred
  UNION SELECT 2, 2 -- (1,2) preferred
  UNION SELECT 2, 3
  UNION SELECT 3, 3
  UNION SELECT 3, 4;

CREATE TABLE matches2 (s INT, d INT);
ALTER TABLE matches2 ADD UNIQUE KEY (s), ADD UNIQUE KEY(d);

INSERT IGNORE INTO matches2 
SELECT * FROM matches ORDER BY s, d;

SELECT * FROM matches2

Выход:

s   d
1   2
2   3
3   4
  • 0
    спасибо за ответ, да, используя временную таблицу, тогда вставка является возможным решением, это метод, который я использую сейчас (с левыми соединениями вместо индексов), но он кажется очень неэффективным.
  • 0
    Я думаю, что индекс, вероятно, более эффективен, чем левое соединение, но было бы интересно посмотреть статистику. Трудность с вашей проблемой заключается в том, что если (например) (1,3) не выбить (1,2), то выбьет (2,3), но потому что (1,3) выбило out, (2,3) попадает в вывод. Так что вам действительно нужно иметь где-то состояние, на которое вы можете посмотреть, и временная таблица - хороший способ получить это. Другой альтернативой, вероятно, является хранимая процедура.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню