在一个SELECT中获取数据(N<->N关系),并将其表示为标题+列数据


Fetching data (N<->N relationship) in one SELECT and presenting it as headers+column data

假设我有一个包含文章(article_id, article_name)的表和另一个包含订购文章的人名(person_id, person_name)的表。加上一个中间表,例如articles-people (article_id, person_id)。

是否有一种优雅的方式,我可以做一个单一的SELECT来获得所有的文章和相关的购买者,这样的文章将列在标题和人列在各自的文章,他们已经买了?

也,是否有一个SELECT,将获取所需的信息,但避免这样的结果(这看起来像一个糟糕的数据库):

  • article_id: 1、article_name:小手电筒,purchaser_id: 1, purchaser_name:弗雷德
  • article_id: 1、article_name:小手电筒,purchaser_id: 2, purchaser_name:阿尔伯特
  • article_id: 1、article_name:小手电筒,purchaser_id: 3, purchaser_name:索尼娅

这将打印出带有值的行。

   $res = mssql_query('SELECT *
        FROM articles a
        join articles-people ap on a.article_id=ap.articleid
        join people p on ap.person_id=p.personid');
    $results = array();
    $finalResuls = array();
    while($row = mssql_fetch_assoc($res))
    {
       $results[] = $row;
    }
    foreach($results as $result)
    {
       /* This makes an array with key:value pairs as string. */
       foreach($result as $k => $v)
       {
          $finalResults[] = $k . ': ' . $v;
       }
       $string = '';
       /* Will concatenate data for each result row into a single string */
       foreach($result as $k => $v)
       {
          $string .= $k . ': ' . $v;
       }
       $finalResults[] = $string;
    }

所以你可以在同一篇文章中有两个解决方案,这是你和JNK谈论的解决方案。

$res = mssql_query('SELECT * from article');
$results = array();
while($row = mssql_fetch_assoc($res))
{
   $id = $row['article_id'];
   $res2 = mssql_query("SELECT * from people p join articles-people ap on p.person_id=ap.person_id where ap.article_id='$id'");
   while($row2 = mssql_fetch_assoc($res2))
   {
      foreach($row2 as $k => $v)
      {
         $results[$id][] = $k . ': ' . $v;
      }
   }
}

这样的美观或显示需求应该在应用程序层处理,而不是在数据库层。

让DB返回不关联的行是可能的,但不推荐。您基本上要求的是返回没有关系信息的数据,这可能会导致问题。

返回您需要的数据,然后相应地过滤显示,这是一个更好的主意。SQL没有针对这样的工作进行优化,在数据库级别格式化显示比在应用级别格式化显示要慢得多,也麻烦得多。