正确使用SELECT WHERE NOT IN

时间:2012-08-14 22:54:19

标签: sql select where notin

我正在为一个带有PHP网络界面的小书店建立一个数据库。对于这个问题,我想显示'产品'表(prod_core)中的所有记录,而不在产品字段'barcode'中具有值的那些记录等于'sales'表(inc_core)中的'description'字段。

我实际上设法让第一个'销售'突变工作,但每当我在'sales'表中添加第二条记录时,查询就不再起作用了。 (除了添加的第一条记录)。这是我的SQL代码:

SELECT prod_core.prodID, prod_core.title, prod_core.location, prod_core.genre,
       prod_core.price, prod_core.barcode
FROM   prod_core
WHERE  prod_core.barcode NOT IN (
         SELECT `description` 
         FROM inc_core
         GROUP BY prod_core.prodID)

我认为它与SQL不循环有关(它停止在表中搜索符合要求的记录)但我不确定。我非常感谢任何帮助!

3 个答案:

答案 0 :(得分:3)

我建议使用LEFT JOIN代替NOT IN

SELECT
    prod_core.prodID, 
    prod_core.title, 
    prod_core.location, 
    prod_core.genre, 
    prod_core.price, 
    prod_core.barcode
FROM 
    prod_core 
    LEFT JOIN inc_core ON inc_core.`description` = prod_core.barcode
WHERE
    inc_core.`description` IS NULL

此外,由于SELECT语句中的所有列都不是聚合函数的一部分,因此我删除了GROUP BY 并将其替换为DISTINCT ...但是,我不明白为什么这个表应该包含重复项。

编辑:我误读了你的查询,虽然group by在外部查询上,而不在子查询上... + +1其他答案抓住了这个。

答案 1 :(得分:2)

您的查询存在的问题是,分组依据是一个字段,但您选择的是另一个字段。这意味着您的子查询正在为每个产品选择任意描述。无法保证您获得了预期的完整列表。

解决此问题的最简单方法是删除群组:

SELECT prod_core.prodID, prod_core.title, prod_core.location, prod_core.genre,
       prod_core.price, prod_core.barcode
FROM prod_core
WHERE prod_core.barcode NOT IN (SELECT `description` FROM inc_core)

然而,这可能效率低下。对于带有子查询的“in”,最佳优化是使用exists。此外,请确保描述中存在索引。这是另一个版本,特别是对于mysql:

SELECT prod_core.prodID, prod_core.title, prod_core.location, prod_core.genre,
       prod_core.price, prod_core.barcode
FROM prod_core
WHERE not exists (select 1 from inc_core where inc_core.description = prod_core.barcode)

就个人而言,我不是相关子查询的忠实粉丝,而是替代“in”。但是,这是mysql最佳优化的方法。

答案 2 :(得分:1)

我认为你不需要group by子句,所以你应该可以使用:

SELECT prod_core.prodID, prod_core.title, prod_core.location, prod_core.genre, prod_core.price, prod_core.barcode
FROM prod_core
WHERE prod_core.barcode NOT IN (SELECT `description` FROM inc_core)