MySQL-选择id不作为外键出现在另一个表中的行

MySQL-选择id不作为外键出现在另一个表中的行,mysql,Mysql,在我的rails应用程序中,我有两个表-设备端口和电路。我的目标是在电路表的physical_port_id列中获取其id未被使用的设备_端口列表 我以前在其他表上也做过类似的操作,但在这里,我的查询只返回一行,而它应该返回23行—此设备有24个设备端口,其中一个正在使用 select id, name, device_id, multiuse from device_ports where (device_id = 6 and multiuse = 1) or device_ports.id

在我的rails应用程序中,我有两个表-设备端口和电路。我的目标是在电路表的physical_port_id列中获取其id未被使用的设备_端口列表

我以前在其他表上也做过类似的操作,但在这里,我的查询只返回一行,而它应该返回23行—此设备有24个设备端口,其中一个正在使用

select id, name, device_id, multiuse
from device_ports
where (device_id = 6 and multiuse = 1)
or device_ports.id not in (select physical_port_id from circuits)
因此,此查询获取所有多用途端口,因此即使外键中引用了id,也应返回此行,并且还应获取设备id为6但未在电路中引用但仅返回多用途行的所有行

查询的结果是

id  | name   | device_id | multiuse
------------------------------------
268 | test-1 |     6     |    1
我确实尝试创建一个sql FIDLE,但构建似乎超时了

CREATE TABLE `device_ports` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `device_id` int(11) DEFAULT NULL,
  `name` tinytext,
  `speed` tinytext,
  `multiuse` tinyint(1) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `id` (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=291 DEFAULT CHARSET=latin1;

INSERT INTO `device_ports` (`id`, `device_id`, `name`, `speed`, `multiuse`, `created_at`, `updated_at`)
*emphasized text*VALUES
(1, 1, 'Test Device Port', '100', 0, NULL, NULL),
(2, 1, 'Test Port 2', '300', 1, NULL, NULL),
(289, 6, 'test-22', '100', 0, NULL, NULL),
(290, 6, 'test-23', '100', 0, NULL, NULL),
(288, 6, 'test-21', '100', 0, NULL, NULL),
(287, 6, 'test-20', '100', 0, NULL, NULL),
(286, 6, 'test-19', '100', 0, NULL, NULL),
(284, 6, 'test-17', '100', 0, NULL, NULL),
(285, 6, 'test-18', '100', 0, NULL, NULL),
(283, 6, 'test-16', '100', 0, NULL, NULL),
(282, 6, 'test-15', '100', 0, NULL, NULL),
(281, 6, 'test-14', '100', 0, NULL, NULL),
(280, 6, 'test-13', '100', 0, NULL, NULL),
(279, 6, 'test-12', '100', 0, NULL, NULL),
(278, 6, 'test-11', '100', 0, NULL, NULL),
(277, 6, 'test-10', '100', 0, NULL, NULL),
(276, 6, 'test-9', '100', 0, NULL, NULL),
(275, 6, 'test-8', '100', 0, NULL, NULL),
(274, 6, 'test-7', '100', 0, NULL, NULL),
(273, 6, 'test-6', '100', 0, NULL, NULL),
(272, 6, 'test-5', '100', 0, NULL, NULL),
(271, 6, 'test-4', '100', 0, NULL, NULL),
(270, 6, 'test-3', '100', 0, NULL, NULL),
(269, 6, 'test-2', '100', 0, NULL, NULL),
(268, 6, 'test-1', '100', 1, NULL, NULL),
(267, 6, 'test-0', '100', 0, NULL, NULL);


CREATE TABLE `circuits` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `organisation_id` int(11) DEFAULT NULL,
  `physical_port_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=248 DEFAULT CHARSET=latin1;

INSERT INTO `circuits` (`id`, `organisation_id`, `physical_port_id`)
VALUES (1, 125, 267);

您可以尝试使用左外部联接:

SELECT DISTINCT d.id, d.name, d.device_id, d.multiuse
 FROM device_ports d
 LEFT OUTER JOIN circuits c ON c.physical_port_id = d.id 
WHERE 
 (c.physical_port_id IS NULL AND d.device_id = 6) 
 OR (d.multiuse = 1 AND d.device_id = 6) 
 ORDER BY d.id 

这个查询有几种技巧,请看。

我尝试过,粘贴在上面的代码给了我25条记录。第一个表是MyISAM,第二个表是InnoDB。。我希望这不会有什么不同。@Sonali很好地发现了。。。不确定这是否会产生影响,25听起来是正确的,因为这应该会给你23个来自设备6的结果和两个来自设备1的结果?我忘了在查询中添加和设备_id=6来过滤这些内容。这意味着您的查询是正确的:@Sonali-hmm,不同的引擎一定会产生影响。使用Drew的原始答案,我可以接近我要查找的内容,尽管存在差异。我接近您的原始答案,但编辑只会再次给我一行。这是我最新的尝试:选择d.id、d.name、d.device_id、d.multiuse从设备_端口d左外部连接电路c在c.physical_端口_id=d.id上,其中c.physical_端口_id为空,d.device_id=6或d.multiuse=1,d.device_id=6按id ASC排序,这几乎是完美的,唯一的“错误”是,如果一个多用途端口被引用,它将在结果中出现两次。可能只是在id上分组,但希望查询是SmartRok。我编辑了我的答案以使用WHERE子句。我添加了一个独特的,这解决了你的重复行吗?
SELECT p.* 
  FROM device_ports p 
  LEFT 
  JOIN circuits c 
    ON c.physical_port_id = p.id 
 WHERE p.device_id = 6 
   AND multiuse = 1 
   AND c.id IS NULL;