Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
高效的MySQL查询,在A中查找与B中不匹配的条目_Mysql_Join_Left Join_Outer Join_Ubercart - Fatal编程技术网

高效的MySQL查询,在A中查找与B中不匹配的条目

高效的MySQL查询,在A中查找与B中不匹配的条目,mysql,join,left-join,outer-join,ubercart,Mysql,Join,Left Join,Outer Join,Ubercart,我有几个表(产品和供应商),想知道哪些项目不再列在供应商表中 表uc_products包含以下产品:。表uc_供应商_csv包含供应商库存。uc_products.model与uc_suppliers.sku合并 当我试图在products表中识别suppliers表中未提及的库存时,我看到了很长的查询。我只想提取匹配条目的nid;sid为空只是为了我可以识别哪些项目没有供应商 对于下面的第一个查询,DB服务器(4GB ram/2x 2.4GHz intel)需要一个小时才能得到结果(507行)

我有几个表(产品和供应商),想知道哪些项目不再列在供应商表中

表uc_products包含以下产品:。表uc_供应商_csv包含供应商库存。uc_products.model与uc_suppliers.sku合并

当我试图在products表中识别suppliers表中未提及的库存时,我看到了很长的查询。我只想提取匹配条目的nid;sid为空只是为了我可以识别哪些项目没有供应商

对于下面的第一个查询,DB服务器(4GB ram/2x 2.4GHz intel)需要一个小时才能得到结果(507行)。我没有等到第二个查询完成

如何使此查询更优化?是因为字符集不匹配吗

我认为以下是最有效的SQL:

         SELECT nid, sid 
           FROM uc_products p
LEFT OUTER JOIN uc_supplier_csv c
             ON p.model = c.sku
         WHERE sid IS NULL ;
对于此查询,我得到以下解释结果:

mysql> EXPLAIN SELECT nid, sid FROM uc_products p LEFT OUTER JOIN uc_supplier_csv c ON p.model = c.sku WHERE sid IS NULL;
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows   | Extra                   |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------------------+
|  1 | SIMPLE      | p     | ALL  | NULL          | NULL | NULL    | NULL |   6526 |                         | 
|  1 | SIMPLE      | c     | ALL  | NULL          | NULL | NULL    | NULL | 126639 | Using where; Not exists | 
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------------------+
2 rows in set (0.00 sec)
我本以为密钥idx_sku和idx_模型在这里是有效的,但它们不是。这是因为表的默认字符集不匹配吗?一个是UTF-8,一个是拉丁语1

我也考虑过这种形式:

SELECT nid 
  FROM uc_products 
 WHERE model 
NOT IN ( 
         SELECT DISTINCT sku FROM uc_supplier_csv 
       ) ;
解释显示该查询的以下结果:

mysql> explain select nid from uc_products where model not in ( select sku from uc_supplier_csv ) ;
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
| id | select_type        | table           | type  | possible_keys         | key     | key_len | ref  | rows   | Extra                    |
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
|  1 | PRIMARY            | uc_products     | ALL   | NULL                  | NULL    | NULL    | NULL |   6520 | Using where              | 
|  2 | DEPENDENT SUBQUERY | uc_supplier_csv | index | idx_sku,idx_sku_stock | idx_sku | 258     | NULL | 126639 | Using where; Using index | 
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
2 rows in set (0.00 sec)
为了不遗漏任何内容,这里有一些更令人兴奋的细节:表的大小和统计数据,以及表的结构:)

编辑:为下面Martin的几个建议查询添加查询计划:

mysql> explain SELECT nid FROM uc_products p WHERE NOT EXISTS ( SELECT 1 FROM uc_supplier_csv c WHERE p.model = c.sku ) ;
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+--------------------------+
| id | select_type        | table | type  | possible_keys | key     | key_len | ref  | rows   | Extra                    |
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+--------------------------+
|  1 | PRIMARY            | p     | ALL   | NULL          | NULL    | NULL    | NULL |   6526 | Using where              | 
|  2 | DEPENDENT SUBQUERY | c     | index | NULL          | idx_sku | 258     | NULL | 126639 | Using where; Using index | 
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+--------------------------+
2 rows in set (0.00 sec)

mysql> explain SELECT nid FROM uc_products WHERE model NOT IN ( SELECT sku  FROM uc_supplier_csv ) ;
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
| id | select_type        | table           | type  | possible_keys         | key     | key_len | ref  | rows   | Extra                    |
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
|  1 | PRIMARY            | uc_products     | ALL   | NULL                  | NULL    | NULL    | NULL |   6526 | Using where              | 
|  2 | DEPENDENT SUBQUERY | uc_supplier_csv | index | idx_sku,idx_sku_stock | idx_sku | 258     | NULL | 126639 | Using where; Using index | 
+----+--------------------+-----------------+-------+-----------------------+---------+---------+------+--------+--------------------------+
2 rows in set (0.00 sec)

也许尝试使用“不存在”而不是“计数”?例如:

SELECT nid 
  FROM uc_products p
 WHERE NOT EXISTS ( 
       SELECT 1 
         FROM uc_supplier_csv c
        WHERE p.model = c.sku
       )
因此,用户Quassnoi概述了一些测试,表明这可能也值得一试:

SELECT nid 
  FROM uc_products
 WHERE model NOT IN ( 
       SELECT sku 
       FROM uc_supplier_csv
       )
基本上按照你原来的查询,没有区别

Chris,这是另一个为您准备的交叉编码连接帮助:

SELECT nid
  FROM uc_products p
 WHERE NOT EXISTS (
       SELECT 1
       FROM uc_supplier_csv c
       WHERE CONVERT( p.model USING latin1 )  = c.sku
       )

在第一个查询中使用have是不正确的——因为没有groupby,所以应该是一个简单的WHERE。我不知道为什么MySQL没有给你一条错误消息,但我想这就是为什么会打乱查询计划!我昨晚在我的笔记本电脑(MBP2.4GHz/4GB/OSX/MAMP MySQL)上测试了这个页面上的四个查询表单。*上面的左外部联接表单需要3526秒才能执行。*上面的子选择表单执行耗时1021秒。*Martin在下面的建议花了637秒执行。*James的略快于Martin的,但返回的结果与其他三个表单不同。此查询是返回正确结果的最快建议解决方案。执行耗时637秒。查询计划是什么样子的?添加到问题中(注释中的格式对我不起作用?)第三次幸运?看上面,哇。0.17秒而不是10分钟。美好的第三个示例(使用上面的WHERE CONVERT()几乎立即给出了正确答案。是关于你认为的皈依者吗?我已经将我的本地表更新为默认的字符集UTF8,但这样做并没有看到任何行为上的变化。
SELECT nid 
  FROM uc_products
 WHERE model NOT IN ( 
       SELECT sku 
       FROM uc_supplier_csv
       )
SELECT nid
  FROM uc_products p
 WHERE NOT EXISTS (
       SELECT 1
       FROM uc_supplier_csv c
       WHERE CONVERT( p.model USING latin1 )  = c.sku
       )