Как сделать обе строки уникальными даже при взаимном обмене в таблице MYSQL? - PullRequest
1 голос
/ 22 марта 2019
id |  sender          | receiver
-------------------------------
1  |    1             | 12           <- case 1
2  |    12            | 1            <- case 2
3  |    1             | 2
4  |    3             | 1 

У меня есть таблица с указанным выше содержимым, и sender, и receiver являются составными ключами, это означает, что я не могу иметь их дважды в одной и той же позиции, но как я могу убедиться, что отправитель или получатель не повторяются, так как отмечены в случаях 1 и 2 выше.

Ответы [ 4 ]

3 голосов
/ 22 марта 2019

Вы можете использовать вычисляемые столбцы вместе с уникальным индексом:

create table mytable
(
  id int not null auto_increment,
  sender int not null,
  receiver int not null,
  key1 int as (least(sender,receiver)),
  key2 int as (greatest(sender,receiver)),
  primary key (id)
);

create unique index idx_mytable_unique on mytable(key1, key2);

Тогда

insert into mytable(sender, receiver) values (1,12);

  -> 1 row inserted.

Тогда

insert into mytable(sender, receiver) values (12,1);

  -> Duplicate entry '1-12' for key 'idx_mytable_unique'

Демо: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a21e48498ff6c10007451109f8e07166

0 голосов
/ 22 марта 2019

использовать кросс-соединение

 select distinct a.*
from cte a cross join cte b
where a.sender<b.sender
0 голосов
/ 22 марта 2019

Одним из вариантов будет использование триггера перед вставкой, чтобы предотвратить это в первую очередь. Другой вариант - ничего не делать, а просто обрабатывать это в своих отчетах. Например, если вы хотите найти все разные пары отправителей и получателей, вы можете использовать LEAST и GREATEST:

SELECT DISTINCT
    LEAST(sender, receiver) AS sender,
    GREATEST(sender, receiver) AS receiver
FROM yourTable;

Если вы намереваетесь сохранить только первую пару, приходящую в определенном порядке, вы можете добавить в таблицу столбец отметки времени и затем агрегировать:

SELECT
    LEAST(t1.sender, t1.receiver) AS sender,
    GREATEST(t1.sender, t1.receiver) AS receiver
FROM yourTable t1
INNER JOIN
(
    SELECT
        LEAST(sender, receiver) AS sender,
        GREATEST(sender, receiver) AS receiver,
        MIN(ts) AS min_ts
    FROM yourTable
    GROUP BY
        LEAST(sender, receiver),
        GREATEST(sender, receiver)
) t2
    ON LEAST(t1.sender, t1.receiver) = t2.sender AND
       GREATEST(t1.sender, t1.receiver) = t2.receiver AND
       t1.ts = t2.min_ts;
0 голосов
/ 22 марта 2019

Это должно работать:

select distinct
       case when sender > receiver then sender else receiver end as sender,
       case when sender > receiver then receiver else sender end as receiver
from MyTable
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...