每个结果的子查询或带有php循环或..的内部联接.


Subqueries for each result or inner join with php loop or ...?

我想在用户的搜索结果中显示他们的照片。不仅是头像照片,还有3张照片。照片在额外的表格user_Photos中。如果我得到每个用户一行,答案将是明确的内部联接。但我会为每个用户获得多行。

我可以使用的第一种方法是加入:

SELECT * FROM users INNER JOIN photos ON photos.user_id=users.user_id

在这种情况下,我需要一些额外的php代码来合并具有相同user_id的结果。类似这样的东西:

foreach($results as $result){
  if(isset($user[$result['user_id']]['age'])){
    $user[$result['user_id']]['photos'][] = $result['photo'];
    continue;
  }      
  $user[$result['user_id']]['age'] = $result['age'];
  $user[$result['user_id']]['photos'][] = $result['photo'];
  //...
}

然后,在视图中,我需要为用户提供第一个第一级循环,然后为每个用户提供$user[$result['user_id']]['photos']数组的第二级循环。

或者我可以对每个结果使用子查询。没有一个选项看起来很优雅,所以我想知道是否还有其他方法。如果不是,第一个选项可能是可行的,对吗?

对于您最初的问题,第一个选项通常是可行的,因为它减少了不必要地发送到数据库的查询数量。

然而,我更喜欢道斯的回答,我认为这几乎是正确的。我要做的一个更改是使加入成为LEFT JOIN,这样没有照片的用户仍然会在查询结果中返回,因此将他的查询更新为:

select u.*, group_concat(photos.name SEPARATOR ' & ') as name
from users u
     join photos on photos.user_id=u.user_id
group by u.user_id;

将返回如下结果:

+-------------------------------------+
|user_id   |photo                     |
+----------+--------------------------+
|1         |photo1 & photo2 & photo7  |
+----------+--------------------------+
|2         |                      NULL|
+----------+--------------------------+
|3         |photo3 & photo5           |
+-------------------------------------+

您想要使用GROUP_CONCT,因此您将得到如下内容:

select u.*, group_concat(photos.name SEPARATOR ' & ') as photonames
from users u
     join photos on photos.user_id=users.user_id
group by a.user_id;

然后,您可以简单地使用explode()来解压缩数组。

第一个选项是可行的,它比第二个选项效率高得多,尽管您要多次检索用户数据(对于每个匹配的图像都会返回)。

第二种选择效率极低,因为它给数据库带来了更多的工作要做,同时也大大增加了脚本和数据库之间的流量。

实际上,我之前展示过的第三个选项可以在这种情况下实现,那就是将照片信息转换为标量值,该标量值表示可以在PHP中使用GROUP BYGROUP_CONCAT()解码的矢量(我过去曾使用JSON),但我不能说我会推荐它,尽管如果你愿意,我会说明它。