【问题标题】:How can I avoid the use of this nested while loop with a SQL query execution inside it?如何避免使用这个嵌套的 while 循环和其中的 SQL 查询执行?
【发布时间】:2016-11-02 16:03:42
【问题描述】:

我必须从这些表中检索某些数据,我认为这些数据是正确的(我认为),但是我实现它的方法非常慢并且可能编程错误,我这样做只是为了我,所以看起来很漂亮代码不是优先级,但它必须在“正常”时间运行,不像现在它在 10-15 秒内运行 ~ 。

这是我的代码:

$arr1=[];

$sqlquery="Select codart,canped,codpro 
           from gcpedl 
           where gcpedl.numped in (
                                   select numped 
                                   from gcpedc 
                                   where texto like '".$_POST['codobra']."'
                                   )";
$query_execute = mssql_query($sqlquery);

while($query_result=mssql_fetch_array($query_execute)){
    $arr1=$query_result;
    $sqlq="Select distinct alart.codart,pultcomp,alart.codpro 
           from alart,gcpedl 
           where gcpedl.numped in 
                 ( select numped 
                   from gcpedc 
                   where texto like '".$_POST['codobra']."') 
                     and alart.codart in 
                        (Select codart 
                         from gcpedl 
                         where numped in 
                             ( select numped 
                               from gcpedc 
                               where texto like '".$_POST['codobra']."')) ";
    $sqlex =mssql_query($sqlq);

    while($sqlre=mssql_fetch_array($sqlex)){
        if (    trim(strtoUPPER($sqlre['codart'])," ")==trim(strtoUPPER($query_result['codart'])," ") 
            and $sqlre['codpro']==$query_result['codpro'] )
        {
            if (    $arr1['codart'] != 'CUADRO' 
                and $arr1['codart'] != 'cuadro' 
                and $arr1['codart'] != 'instalacion' 
                and $arr1['codart'] != 'INSTALACION')
            {
                $materiales= $materiales+ ($sqlre['pultcomp']*$arr1['canped']);
            }
        }
    }

编辑:这段代码的目的是遍历每一篇文章(codart),并获取它的数量(canped)和它的提供者(codpro),然后循环遍历另一个表中的每一篇文章,并匹配 codart 和供应商,并取出价格(pultcomp)乘以数量。

Edit2:要从第一个表(gcpedl)和第二个表(alart)中选择文章,我必须使用第三个表(gcpedc)和 where 子句对它们进行子选择(或加入)。

Edit3:仅使用一个查询无法使其工作,我走得更远是这样的:

$arr1=[];

$sqlquery="Select  g1.codart,
                g1.canped,
                g1.codpro 
        from gcpedl as g1
        inner join gcpedc as g2
            ON g1.numped = g2.numped
        where g2.texto like '".$_POST['codobra']."'";
  $query_execute = mssql_query($sqlquery);

while($query_result=mssql_fetch_array($query_execute)){
    $arr1=$query_result;
        $sqlq="Select distinct  a.codart,
                    a.pultcomp,
                    a.codpro 
    from alart AS a
    inner join gcpedl AS g
        on a.codart = g.codart 
    inner join gcpedc g1
        on g.numped = g1.numped 
    where g.numped in (select numped from gcpedc where texto like '".$_POST['codobra']."') ";
    $sqlex =mssql_query($sqlq);

    while($sqlre=mssql_fetch_array($sqlex)){if (trim(strtoUPPER($sqlre['codart'])," ")==trim(strtoUPPER($query_result['codart'])," ") and $sqlre['codpro']==$query_result['codpro'] ){
        if ($arr1['codart'] != 'CUADRO' and $arr1['codart'] != 'cuadro' and $arr1['codart'] != 'instalacion' and $arr1['codart'] != 'INSTALACION'){
$materiales= $materiales+ ($sqlre['pultcomp']*$arr1['canped']);}

我终于解决了,只是我太睡了,查询可以转换为只有1个查询,执行时间大大减少。

Select gcpedl.codart, (gcpedl.canped*alart.pultcomp) as precio, alart.codpro from alart,gcpedl where gcpedl.numped in (Select numped from gcpedc where texto like '".$_POST['codobra']."') and alart.codart=gcpedl.codart and alart.codpro=gcpedl.codpro 

【问题讨论】:

  • 您很容易受到sql injection attacks 的攻击,并且几乎在您进行嵌套查询的任何时候,并且内部查询使用来自外部查询的数据,您应该将其重写为单个joined 查询。
  • 您在第二个查询中没有使用第一个查询中的任何内容。你真的需要每次都运行它吗?
  • 一些合理的代码缩进是个好主意。它帮助我们阅读代码,更重要的是,它将帮助 您调试代码 Take a quick look at a coding standard 为您自己谋取利益。您可能会被要求在几周/几个月内修改此代码,最后您会感谢我的。
  • sql 注入攻击在这种情况下不是问题,这就是为什么我没有解决它,我一直在寻找如何加入这些查询,但我没有成功

标签: php sql sql-server loops


【解决方案1】:

您可以使用正确的 JOIN 语句来避免它们。

$sqlq="Select distinct  a.codart,
                        g.pultcomp,
                        g1.canped,
                        a.codpro 
        from alart a
        inner join gcpedl g
            on a.codart = g.codart 
        inner join gcpedc g1
            on g.numped = g1.numped 
        where g.texto like '".$_POST['codobra']."' and g1.texto like '".$_POST['codobra']."' ";

试一试。

【讨论】:

  • 这是作为原始代码工作(按预期),但它也很慢,问题是我正在处理在第一个 while 的每个循环中执行的查询,我必须找到一个我在循环中没有任何 sql 查询执行的解决方案。
  • 然后检查您的表上是否有正确的索引。 codartnumped 列上必须有索引。如果您传递类似'%some_word%'(通配符搜索)的内容,您也可以使用LIKE,您可能会在大型表上获得非常慢的性能。
  • 你在第一个查询中循环的目的是什么?
  • 我在 LIKE 语句中不使用通配符,关于索引我认为这不是问题,但我对索引不太擅长。
  • 这段代码的目的是遍历每篇文章(codart),并获取它的数量(canped)和它的提供者(codpro),然后循环遍历另一个表中的每一篇文章并匹配codart 和提供者,并取出价格(pultcomp)以将其乘以数量,我在主帖上编辑此内容。编辑:要从第一个表中选择文章,我必须对它们进行子选择(或加入第三个表)。
猜你喜欢
  • 2019-09-25
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 2012-08-20
  • 1970-01-01
  • 2013-08-29
  • 1970-01-01
相关资源
最近更新 更多