在MySQL中,检查一组值是否等于另一组值;不在乎顺序

时间:2018-10-26 21:08:53

标签: mysql

我正在检查一个表的2个外来ID是否等于同一张表中另一个表中的2个外键,但是我不在乎这些ID的顺序,只是它们具有相同的值。 / p>

SELECT (1, 2, 3) = (1, 2, 3);
> 1

SELECT (1, 2, 3) = (2, 1, 3);
> 0

我想要一种使(1,2,3)(2,1,3)以及(1,3,2)(2,3,1)匹配的方法。

不幸的是,很难找到有关此信息的信息,大多数建议是“ MySQL中不存在列表”,然后搜索排序或无序检查导致各种不相关的SQL调用。

提琴:https://www.db-fiddle.com/f/eqz27tR9uDMQriDhkwBo2a/0

我故意将event放在表中,参与者的顺序与not_event中的参与者的顺序不同,那就是联接

SELECT * FROM event
 JOIN not_event ON (
  (event.participant_1_id, event.participant_2_id) =
  (not_event.participant_1_id, not_event.participant_2_id));

这就是问题所在。我不在乎两个表中participant_1_idparticipant_2_id的顺序,只要它们是相同的2。

从小提琴中提取代码,

CREATE TABLE `participant` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `key` varchar(15) NOT NULL,
  PRIMARY KEY (`id`));

CREATE TABLE `event` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `participant_1_id` int(11) NOT NULL,
  `participant_2_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `event_ibfk_1` FOREIGN KEY (`participant_1_id`) REFERENCES `participant` (`id`),
  CONSTRAINT `event_ibfk_2` FOREIGN KEY (`participant_2_id`) REFERENCES `participant` (`id`)
);

CREATE TABLE `not_event` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `participant_1_id` int(11) NOT NULL,
  `participant_2_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `not_event_ibfk_1` FOREIGN KEY (`participant_1_id`) REFERENCES `participant` (`id`),
  CONSTRAINT `not_event_ibfk_2` FOREIGN KEY (`participant_2_id`) REFERENCES `participant` (`id`)
);

INSERT INTO `participant` VALUES (1, 'Team1');
INSERT INTO `participant` VALUES (2, 'Team2');

INSERT INTO `event` VALUES (NULL, 1, 2);
INSERT INTO `not_event` VALUES (NULL, 2, 1);

SELECT (1, 2, 3) = (1, 2, 3);
SELECT (1, 2, 3) = (2, 1, 3);

SELECT * FROM event
 JOIN not_event ON (
 (event.participant_1_id, event.participant_2_id) =
 (not_event.participant_1_id, not_event.participant_2_id));


SELECT * FROM event
 JOIN not_event ON (
 (event.participant_1_id, event.participant_2_id) =
 (not_event.participant_2_id, not_event.participant_1_id));

2 个答案:

答案 0 :(得分:1)

一些选择,我真的不满意,

对于只有2个字段的二进制联接,使用LEASTGREATEST可以,但是在2个以上的字段上则不起作用,

SELECT * FROM event
 JOIN not_event ON (
  LEAST(event.participant_1_id, event.participant_2_id) =
  LEAST(not_event.participant_1_id, not_event.participant_2_id)
   AND
  GREATEST(event.participant_1_id, event.participant_2_id) =
  GREATEST(not_event.participant_1_id, not_event.participant_2_id));

之后,似乎LENGTH检查效率低下,其中多个REPLACECONCAT_WS

SELECT * FROM event
 JOIN not_event ON (
 1 = LENGTH(REPLACE(REPLACE(
   CONCAT_WS(
     ',', event.participant_1_id, event.participant_2_id),
   not_event.participant_1_id, ''), not_event.participant_2_id, ''))
 );

但是这很烂,并且不可靠,因为“ 1”将“ 11”替换为“”,“ 2”将“ 222”替换为“”,依此类推。

更新的小提琴(使用这些解决方案):https://www.db-fiddle.com/f/eqz27tR9uDMQriDhkwBo2a/1

答案 1 :(得分:0)

我发现,您可以通过3种不同的方法实现这一目标。 1是查询eventnot_event表,并将participant表连接两次,将它们分组在一起,并运行GROUP BYHAVING比较{{1 }},

GROUP_CONCAT

或者通过在您有兴趣加入的字段上运行两个SELECT event.*, not_event.* FROM event JOIN participant p1 ON p1.id IN (event.participant_1_id, event.participant_2_id), not_event JOIN participant p2 ON p2.id IN (not_event.participant_1_id, not_event.participant_2_id) GROUP BY event.id, not_event.id HAVING GROUP_CONCAT(p1.key ORDER BY p1.key) = GROUP_CONCAT(p2.key ORDER BY p2.key) 子查询,然后再将其加入,

GROUP_CONCAT

然后是超级“直接”或手动方式,

SELECT *
FROM (
 SELECT GROUP_CONCAT(participant.id ORDER BY participant.id) `key`, event.*
 FROM event
 JOIN participant ON (participant.id IN (event.participant_1_id, event.participant_2_id))
 GROUP BY event.id) _event

JOIN (
 SELECT GROUP_CONCAT(participant.id ORDER BY participant.id) `key`, not_event.*
 FROM not_event
 JOIN participant ON (participant.id IN (not_event.participant_1_id, not_event.participant_2_id))
 GROUP BY not_event.id) _not_event

ON _event.key = _not_event.key;

这些都可以根据需要正确加入。

更新的小提琴: https://www.db-fiddle.com/f/eqz27tR9uDMQriDhkwBo2a/5

对于这两种解决方案, SELECT event.*, not_event.* FROM event, not_event WHERE event.participant_1_id IN (not_event.participant_1_id, not_event.participant_2_id) AND event.participant_2_id IN (not_event.participant_1_id, not_event.participant_2_id) AND not_event.participant_1_id IN (event.participant_1_id, event.participant_2_id) AND not_event.participant_2_id IN (event.participant_1_id, event.participant_2_id) 可以正确地与Event(1, 2)联接,并且没有其他任何选择,而NotEvent(2, 1)可以正确地与Event(2, 3)联接,没有其他选择。

我的还是的认为这是疯狂的,你必须参加这样的表,这样,而不是仅仅比较直接在表内的键,但这些工作,这种或那种方式。< / p>