【问题标题】:Can't query names from a table that does not exist in another table无法从另一个表中不存在的表中查询名称
【发布时间】:2018-09-27 17:12:21
【问题描述】:

我有两个字段相同的表。我想查询table2 中不在table1 中的名称。两个表都有 name 字段作为唯一(主键)。

这里是信息。我的数据库设计: 我的查询是:

SELECT `table2`.`name` FROM `mydatabase`.`table2`, `mydatabase`.`table1` 
WHERE `table2`.`name` NOT IN (SELECT  `table1`.`name` FROM `mydatabase`.`table1`)
AND table2`.`name` NOT LIKE 'xyz%';

SHOW CREATE TABLE <table name>:的输出

对于table1

table1, CREATE TABLE `table1` (
  `name` varchar(500) NOT NULL,
  `ip` varchar(500) DEFAULT NULL,
  `type` varchar(500) DEFAULT NULL,
  `grade` varchar(500) DEFAULT NULL,
  `extended_ip` text,
  PRIMARY KEY (`name`),
  UNIQUE KEY `mydatabase_name_UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

还有table2

tabl2, CREATE TABLE `table2` (
  `name` varchar(500) NOT NULL,
  `ip` varchar(500) DEFAULT NULL,
  `type` varchar(500) DEFAULT NULL,
  `grade` varchar(500) DEFAULT NULL,
  `extended_ip` text,
  PRIMARY KEY (`name`),
  UNIQUE KEY `mydatabase_name_UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

The output of EXPLAIN <my query>:

# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
1, PRIMARY, table1, , index, , mydatabase_name_UNIQUE, 502, , 17584, 100.00, Using index
1, PRIMARY, table2, , index, , mydatabase_name_UNIQUE, 502, , 46264, 100.00, Using where; Using index; Using join buffer (Block Nested Loop)
2, SUBQUERY, table1 , index, PRIMARY,mydatabase_name_UNIQUE, mydatabase_name_UNIQUE, 502, , 17584, 100.00, Using index

编辑: 我忘了提到发生的事情是数据库只是因为我的查询而崩溃。我在Ubuntu 18 中使用mysql-workbench。当我执行此查询时,整个工作台将关闭,我必须重新打开它。

【问题讨论】:

    标签: mysql sql join inner-join


    【解决方案1】:

    只需在name 上执行LEFT JOIN,将table2 作为起始表,因为您要考虑table2 中不存在的所有 名称在table1 . table1 中不存在的名称将在加入后具有 null 值。请注意,这种基于联接的解决方案将比任何基于子查询的方法快得多。

    此外,您应该避免基于 逗号 (,) 的隐式连接。这是旧语法,您应该使用基于 JOIN 的显式语法。阅读:Explicit vs implicit SQL joins

    另外,使用Aliasing 以提高可读性是一个好习惯

    尝试以下方法:

    SELECT t2.name 
    FROM `mydatabase`.`table2` AS t2
    LEFT JOIN `mydatabase`.`table1` AS t1 ON t1.name = t2.name 
    WHERE t1.name IS NULL 
      AND t2.name NOT LIKE 'xyz%';
    

    【讨论】:

    • 这也有效,并且可能比使用子查询更有效:)
    【解决方案2】:

    尝试子查询:

    SELECT `table2`.`name` FROM `mydatabase`.`table2` WHERE `table2`.`name` NOT IN (SELECT `table1`.`name` FROM `mydatabase`.`table1`);
    

    【讨论】:

    • 我的查询的其余部分怎么样(我也有 LIKE 语句)。你能完成你的查询吗?
    • 另外,如果你看到我的查询,我已经在使用像你这样的子查询了。
    • 如果您的目标只是查询 table2 中不在 table1 中的名称,那么我的答案就是您想要的。在 From 中拥有两个表会给您带来问题。如果您对 table2.name 有其他条件,则可以将其放在子查询之后的 WHERE 中:AND table2.name` NOT LIKE 'xyz%';
    • 感谢您选择我的答案,但也请考虑@Madhur Bhaiya 的答案。在许多情况下,LEFT JOIN 和检查 IS NULL 会更有效。
    猜你喜欢
    • 2012-08-18
    • 1970-01-01
    • 2017-12-08
    • 2013-11-12
    • 2014-12-15
    • 2012-06-11
    • 2010-09-26
    • 2017-11-22
    • 1970-01-01
    相关资源
    最近更新 更多