Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.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
Php 使用SELECT IN MySQL更快地搜索IN语句_Php_Mysql_Sql - Fatal编程技术网

Php 使用SELECT IN MySQL更快地搜索IN语句

Php 使用SELECT IN MySQL更快地搜索IN语句,php,mysql,sql,Php,Mysql,Sql,我目前正在为我的应用程序执行一些查询,我需要获取当前位置上最近的商店,要执行此操作,首先我需要获取所有具有相同名称的项目,然后获取其信息并缩减该查询。现在我在这个语句中使用了,但由于正在搜索的项目也基于列表,因此我需要使用另一个select。到目前为止,这是我的代码: select * from product p, store s, branches b where 1 = 1 and b.idproduct = p.idproduct and p.store = s.idstore and

我目前正在为我的应用程序执行一些查询,我需要获取当前位置上最近的商店,要执行此操作,首先我需要获取所有具有相同名称的项目,然后获取其信息并缩减该查询。现在我在这个语句中使用了,但由于正在搜索的项目也基于列表,因此我需要使用另一个select。到目前为止,这是我的代码:

select *
from product p,
store s,
branches b
where 1 = 1
and b.idproduct = p.idproduct
and p.store = s.idstore
and common_name IN(SELECT p.common_name
FROM shopping_list_content s, product p
WHERE 1 =1
AND s.iditem = p.idproduct
AND s.idlist =$listid)

现在它可以按我所希望的那样工作,但我希望它能更快地完成查询。目前,这个查询的运行速度要比这个快3秒多。如果不到一秒钟,效果会更好。我还可以使用其他选项吗?

这是您的查询,可以使用正确的
join
语法:

select *
from product p join
     store s
     on p.store = s.idstore join
     branches b
     on b.idproduct = p.idproduct
where p.common_name IN (SELECT p.common_name
                        FROM shopping_list_content slc join
                             product p
                             ON slc.iditem = p.idproduct AND
                                slc.idlist = $listid
                       );
假设相同的
common\u名称
没有出现在多个产品上,并且
购物列表内容
没有重复的行,您可以用简单的
连接来替换它:

select *
from product p join
     store s
     on p.store = s.idstore join
     branches b
     on b.idproduct = p.idproduct join
     shopping_list_content slc
     on slc.iditem = p.idproduct and
        slc.idlist = $listid;
然而,这些假设可能并不正确。在这种情况下,将子查询更改为使用
exists
可能有助于提高性能:

select *
from product p join
     store s
     on p.store = s.idstore join
     branches b
     on b.idproduct = p.idproduct
where exists (SELECT 1
              FROM shopping_list_content slc join
                   product p2
                   on slc.iditem = p2.idproduct AND
                      slc.idlist = $listid
              WHERE p.common_name = p2.common_name
             );

对于后一个查询,
product(common\u name,idproduct)
上的索引以及
shopping\u list\u内容(iditem,idlist)
应该会有所帮助。

MySQL在优化子查询时遇到困难,例如:

SELECT  *
FROM    T
WHERE   T.ID (SELECT ID FROM T2);
它有时被改写为

SELECT  *
FROM    T
WHERE   EXISTS
        (   SELECT  1
            FROM    T2
            WHERE   T.ID = T2.ID
        );
然后在
T
中每行执行一次子查询,而如果您写入:

SELECT  T.*
FROM    T
        INNER JOIN
        (   SELECT  DISTINCT ID
            FROM    T2
        ) T2
            ON T2.ID = T.ID;
您的结果集将是相同的,但是MySQL将首先用子查询的结果填充内存中的表,并将其散列在T2.ID上,然后只需要针对
T
中的每一行查找该散列表

您想要的行为实际上取决于您希望从每个表/子查询中获得多少数据。如果在
T2
中有100万行,在
T
中有10行,那么用100万行填充一个临时表是没有意义的,只是随后只使用它10次,然而,如果在
T
中有大量行,而在
T2
中只有少量行,那么从长远来看,实现子查询的额外成本将是有益的

需要指出的另一点是(这对性能没有影响),您使用的连接语法是ANSI 89语法,20多年前被ANSI 92显式连接语法取代。虽然针对SQL Server,但我认为可以很好地总结切换到较新联接语法的原因。进行最终查询:

SELECT  *
FROM    product p,
        INNER JOIN store s
            ON p.store = s.idstore
        INNER JOIN branches b
            ON b.idproduct = p.idproduct
        INNER JOIN
        (   SELECT DISTINCT p.common_name
            FROM    shopping_list_content s
                    INNER JOIN product p
                        ON s.iditem = p.idproduct
            WHERE   s.idlist =$listid
        ) s
            ON s.common_name = p.common_name;

注意:如果您使用的是MySQL 5.6.5或更高版本,以上大部分内容不适用。在这个版本中,他们引入了更多解决上述许多问题的方法

对您的查询做一个解释,检查索引,并寻找用JOIN1=1替换In,将给出所有行为什么在每个查询/子查询中使用
1=1
子句?如果你让其他人知道WHERE子句我错了,那就没有意义了?请尝试更改为存在,如
和common\u name IN(选择p.common\u name
和common\u name EXIST(选择1…
我现在将尝试加入。)这真的很好!我的意思是解释MySQL是如何处理它的。哇!这是一个非常快速的解决方案。完成查询只需要0.0480秒。非常感谢!:D