MYSQL查询问题 - 无法搞清楚

时间:2011-06-25 12:53:44

标签: php mysql

Hy,我有一个很大的问题......听起来很简单但实际上很复杂

我有两个mysql表:

info_cat (id, name)
info_subcat (id, id_info_cat, name)

我想向用户显示info_cat.name后跟info_subcat.name,但问题是info_cat.name我想只出现一次。 像这样:

笔记本

  • HP
  • 索尼

HDD

  • Western DIgital
  • 希捷
  • ETC

所以,我会像这样查询(老式的)

$query = mysql_query("SELECT * FROM info_cat");
while ($row = mysql_fetch_assoc($query)) {
$id_info_cat = $row['id'];
echo $row['name']; 
 $query2 = mysql_query("SELECT * FROM info_subcat WHERE id_info_cat = '$id_info_cat'");
 while($row2 = mysql_fetch_assoc($query2)) {
 echo $row2['nume'];
 }
}

我有while within while。 我的问题是我怎么能只用一个查询来实现这个(我想用JOIN)? 我尝试了以下命令:

SELECT info_cat.name, info_subcat.name AS name2, info_subcat.id FROM info_cat, info_subcat WHERE info_cat.id = info_subcat.id_info_cat;

但无法弄清楚如何操作数据,因为它会输出:

name       name2                 id
Laptop     Acer                  1
Laptop     HP                    2
Laptop     Sony                  3
HDD        Western Digital       4
HDD        Seagate               5
HDD        ETC                   6

我只想回复笔记本电脑一次,硬盘驱动器一次,然后是它的子名称。 我怎么能这样做?

Pleaseee ....

谢谢

6 个答案:

答案 0 :(得分:2)

嵌套while循环没有任何问题,当他们完美地描述问题时(列表中的列表)。但是,如果您想不惜一切代价避免嵌套while循环,可以执行以下操作:

$query = mysql_query("
     SELECT ic.name ic_name, isc.name isc_name
       FROM info_cat ic
  LEFT JOIN info_subcat isc
         ON ic.id = isc.id_info_cat
   ORDER BY ic_name ASC");

$last_cat = '';
while ($row = mysql_fetch_assoc($query)) {
  if($row['ic_name'] != $last_cat) {
    echo $row['ic_name']; 
    $last_cat = $row['ic_name'];
  }
  echo $row['name'];
}

应该可以在没有ORDER BY语句的情况下编写上述查询,从而获得一点性能。使用ORDER BY更明确一点,并保证(SQL标准不规定行的某些排序,可以是任何东西)结果集的正确排序和输出(尽管mysql通常做你期望的)。

答案 1 :(得分:1)

在查询中使用group by

SELECT info_cat.name, info_subcat.name AS name2, info_subcat.id FROM info_cat inner join info_subcat on info_cat.id = info_subcat.id_info_cat
group by info_cat.name
order by info_cat.name desc

然后在你的while循环中,执行if检查以查看info_cat name = last info_cat name是否相等然后不添加它,否则添加它 例如(这是下面的psedocode)

$lastInfoCatName = $row['name']; 
while ($row != null)
{
if ($lastInfoCatName != $row['name']
{
$lastInfoCatName = $row['name']
//work on creating the table
}

答案 2 :(得分:1)

尝试使用GROUP BY和GROUP_CONCAT。

SELECT
    info_cat.name,
    GROUP_CONCAT(info_subcat.name ORDER BY info_subcat.name SEPARATOR ', ')
FROM
    info_cat
        LEFT JOIN
    info_subcat ON (info_car.id = info_subcat.id_info_cat)
GROUP BY
    info_cat.id

答案 3 :(得分:1)

有几种方法可以做到这一点。为了完成,我将列出两者。

方法#1

$query = <<<SQL
   SELECT
      ic.name catname
      , is.name subcatname
   FROM
      info_cat ic
      JOIN info_subcat is ON (ic.id = is.info_cat_id)
SQL;

$result = mysql_query($query);

$cats = array();
while ($row = mysql_fetch_object($result)) {
   if ( ! isset($cats[$result->catname]) ) {
      $cats[$result->catname] = array();
   }
   $cats[$result->catname][] = $result->subcatname;
}

foreach ($cats as $catname => $subcats) {
   echo "$catname<br /> <ul>";
   foreach ($subcats as $subcat) {
      echo "<li>$subcat</li>";
   }
   echo "</ul>";
}

方法#2

$query = <<<SQL
   SELECT
      ic.name catname,
      GROUP_CONCAT(is.name) subcatnames
   FROM
      info_cat ic
      JOIN info_subcat is ON (ic.id = is.info_cat_id)
SQL;

$result = mysql_query($query);

while ($row = mysql_fetch_object($result)) {
   echo "$row->name<br /><ul>"
   foreach (explode(',', $row->subcatnames) as $subcatname) {
      echo "<li>$subcatname</li>";
   }
   echo "</ul>";
}

由于其他人也会建议它,你应该使用PDO和PHPTAL,当你创建一个表时,你应该给“id”列一个引用表的名称,如“icID”和“isID”

答案 4 :(得分:0)

您发布的结果看起来像是mysql结果,而不是根据您的脚本输出的PHP。

迭代主要类别,它将回显名称,它将遍历其子类别并回显子名称并继续前进。

在你的例子中没有任何地方可以产生这样的输出......

答案 5 :(得分:0)

SELECT info_cat.name, GROUP_CONCAT(info_subcat.name) AS name2
FROM info_cat, info_subcat
WHERE info_cat.id = info_subcat.id_info_cat
GROUP BY info_cat.name;

CONCAT! :)