【问题标题】:Select from one table where not in another从一个表中选择,而不是在另一个表中
【发布时间】:2011-11-27 14:33:00
【问题描述】:

我正在尝试查找在一个表中但不在另一个表中的行,这两个表位于不同的数据库中,并且在我用来匹配的列上也有不同的列名。

我有一个查询,下面的代码,我认为它可能有效,但它太慢了:

SELECT `pm`.`id`
FROM `R2R`.`partmaster` `pm`
WHERE NOT EXISTS (
    SELECT * 
    FROM `wpsapi4`.`product_details` `pd`
    WHERE `pm`.`id` = `pd`.`part_num`
)

所以查询试图做如下:

从 R2R.partmaster 数据库中选择不在 wpsapi4.product_details 数据库中的所有 id。我匹配的列是 partmaster.id & product_details.part_num

【问题讨论】:

  • 对我来说存在/不存在是最好的方式,因为表达清楚地想要你想要得到。但似乎是最慢的方式(在 MySQL 上)。检查这个:explainextended.com/2009/09/18/…

标签: mysql sql


【解决方案1】:

您可以 LEFT JOIN 两个表。如果第二个表中没有对应的行,则值为NULL。

SELECT id FROM partmaster LEFT JOIN product_details ON (...) WHERE product_details.part_num IS NULL

【讨论】:

    【解决方案2】:

    扩展 Sjoerd 的反连接,你也可以使用易于理解的SELECT WHERE X NOT IN (SELECT) 模式。

    SELECT pm.id FROM r2r.partmaster pm
    WHERE pm.id NOT IN (SELECT pd.part_num FROM wpsapi4.product_details pd)
    

    请注意,您只需要在保留字、带空格的名称等上使用` 反引号,而不是普通的列名。

    在 MySQL 5+ 上,这种查询运行得非常快。
    在 MySQL 3/4 上它很慢。

    确保您有相关字段的索引
    您需要在pm.idpd.part_num 上有一个索引。

    【讨论】:

    • 感谢您的回答,它的工作速度不够快,但查询很好,只是不在我的数据库上。我已经制定了另一个解决方案,但 stackOverflow 直到 3 小时才会让我发布。
    • 请注意,在 MySQL 5.1.73a 上,类似上面的查询大约需要 10 分钟。当我升级到 MySQL 5.6.22 大约需要 456 毫秒。
    • 查看@colmaclean 对空值的回答
    • 我唯一要添加的是“WHERE pd.part_num IS NOT NULL”到内部选择查询。
    【解决方案3】:

    所以网上有很多帖子展示了如何做到这一点,我找到了 3 种方法,与 Johan & Sjoerd 指出的相同。我无法让这些查询中的任何一个工作,很明显它们工作正常,这是我的数据库工作不正常,而且这些查询都运行得很慢。

    所以我想出了另一种可能对其他人有用的方法:

    它的基本要点是创建一个临时表并用所有信息填充它,然后删除另一个表中的所有行。

    所以我做了这 3 个查询,它运行得很快(在几分钟内)。

    CREATE TEMPORARY TABLE
    
    `database1`.`newRows`
    
    SELECT
    
    `t1`.`id` AS `columnID`
    
    FROM
    
    `database2`.`table` AS `t1`
    

    .

    CREATE INDEX `columnID` ON `database1`.`newRows`(`columnID`)
    

    .

    DELETE FROM `database1`.`newRows`
    
    WHERE
    
    EXISTS(
        SELECT `columnID` FROM `database1`.`product_details` WHERE `columnID`=`database1`.`newRows`.`columnID`
    )
    

    【讨论】:

    • 它运行得很快,因为它只是比较第一个产品,或者我没有看到这个?!
    【解决方案4】:

    为了扩展 Johan 的回答,如果子选择中的 part_num 列可以包含空值,那么查询将中断。

    要更正此问题,请添加一个空检查...

    SELECT pm.id FROM r2r.partmaster pm
    WHERE pm.id NOT IN 
          (SELECT pd.part_num FROM wpsapi4.product_details pd 
                      where pd.part_num is not null)
    
    • 抱歉,由于没有代表,我无法添加评论!

    【讨论】:

    • not in 肯定很讨厌
    猜你喜欢
    • 2013-01-06
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    相关资源
    最近更新 更多