我想在用户的搜索结果中显示他们的照片。不仅是头像照片,还有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 BY
和GROUP_CONCAT()
解码的矢量(我过去曾使用JSON),但我不能说我会推荐它,尽管如果你愿意,我会说明它。