如何使用 SQL 避免循环内的查询

Posted

技术标签:

【中文标题】如何使用 SQL 避免循环内的查询【英文标题】:How to use SQL to avoid queries within loops 【发布时间】:2013-09-25 10:15:07 【问题描述】:

我目前有两个相关表,一个用于“组”,另一个用于“项目”。项目按关联的组 ID 存储在组中。非常基本的表关系,但不幸的是我的 SQL 不是很好,所以我不确定循环所有组的最佳方法是什么,并在其中循环所有项目以最终得到按组分类的所有项目的列表。

目前我有这个代码:

$query = "SELECT ID AS GRPID, Description FROM Groups_Inv ORDER BY SortNum ASC";
try  
  $result = odbc_exec($connect,$query); 
  if($result) 
    while ($groups = odbc_fetch_array($result)) 
      echo "<li title='".$groups['DESCRIPTION']."' class='category'>
            <h3><span><a class='category'>".
              $groups['DESCRIPTION'].
           "</a></span></h3><ul class='sub-menu'>\n";
      $subquery = "SELECT ID AS ITEM_ID, Description
                   FROM Items_Inv WHERE grpID = ".$groups['GRPID']."";
      $subresult = odbc_exec($connect,$subquery);
      while ($items = odbc_fetch_array($subresult)) 
        echo "<li class='sub_item' title='".$items['DESCRIPTION']."'>
              <input type='radio' class='addRow'>
                <label for='".$items['ITEM_ID']."'>".
                  $items['DESCRIPTION'].
               "</label></li>\n";
      
      echo "</ul></li>\n";
    
   
  else 
    throw new RuntimeException("Failed to connect."); 
   
 
catch (RuntimeException $e)  
  print("Exception caught: $e");

我知道在循环中使用 SQL 查询是一个非常糟糕的主意,这就是我想优化这段代码的原因,但不幸的是,除了基本的 CRUD 内容之外,我对 SQL 的了解非常有限。

我还希望能够不显示没有项目的组,但我不能用这段代码真正做到这一点。能够在一个查询中获取所有组和关联项以及仅指定选择具有关联项的组的最佳方法是什么?

【问题讨论】:

【参考方案1】:

你试过了吗:

$query = "SELECT ID AS GRPID, Description, ID AS ITEM_ID, Description AS ITEM_DESC
FROM Groups_Inv 
LEFT JOIN Items_Inv ON (Groups_Inv.ID = ITEM_Inv.ID)
ORDER BY SortNum ASC";

【讨论】:

感谢您的帮助,但不幸的是,这对我来说不太适用,因为它似乎也选择了没有项目的组。我还想订购结果,以便每个组描述都列出一次,并且所有项目都列在该组下。我将如何实现这一目标? 将 LEFT JOIN 更改为 INNER JOIN。如果这不起作用,请尝试 RIGHT JOIN。【参考方案2】:

我认为,这很好,你可以使用一个查询,例如:

SELECT ii.ID AS ITEM_ID, ii.Description AS item_desc, gi.Description AS group_desc  FROM Items_Inv ii INNER JOIN Groups_Inv gi ON ii.grpID=gi.ID

您将获得一个包含所有项目的表格,其中包含组描述,但组描述将在项目旁边重复。你可以按 foreach all 排序,但更好的主意是你的解决方案。

【讨论】:

【参考方案3】:
SELECT g.ID AS GRPID, g.Description AS GrpDesc,i.ID AS ItemId, i.Description AS ItemDescription
FROM Groups_Inv g
LEFT JOIN Items_Inv i
ON g.ID=i.grpID
ORDER BY g.SortNum ASC

此查询将返回所有包含相应项目的组。

【讨论】:

谢谢,这行得通,但是我如何循环它,所以我只打印一次组描述,但打印该组下的所有项目?

以上是关于如何使用 SQL 避免循环内的查询的主要内容,如果未能解决你的问题,请参考以下文章

我如何编写一个 python/pandas 循环来将 sql 查询中的日期增加一天

IN 谓词在 SQL 中如何工作?

如何在 sql 查询中使用 c++ 中的 pqxx 为 postgresql 执行 IN?

如何在 Hive/SQL 的 where/have 子句中使用 min()(以避免子查询)

如何动态准备 SQL 查询(也包括列名)避免 SQL 注入

SQL - 如何避免将三个查询合并为一个