我有两个表:activity
和tag
。一个activity
有许多tags
。我需要优化当前的设置,我们在表中查找所有活动,然后遍历每个活动以查找所有标记。最后,我们将内容作为JSON处理。
以下是一个例子:
-- Query that we execute one time
SELECT `id`, `name`
FROM `activity`
-- Query that we execute N times
SELECT `id`, `name`, `color`
FROM `tag`
WHERE `tag`.`activityId` = $activityId
所以我们的最终代码看起来像这样:
$result = mysqli_query("
SELECT `id`, `name`
FROM `activity`
");
$data = array();
for ($i=0; $i<mysqli_num_rows($result); $i++) {
$row = mysqli_fetch_assoc($result);
$data[$i]["activityId"] = $row["id"];
$data[$i]["name"] = $row["name"];
$data[$i]["tags"] = array();
$activityId = $row["id"];
$resultTags = mysqli_query("
SELECT `id`, `name`, `color`
FROM `tag`
WHERE `tag`.`activityId` = $activityId
");
for ($j=0; $j<mysqli_num_rows($resultTags); $j++) {
$row = mysqli_fetch_assoc($resultTags);
$data[$i]["tags"][$j]["name"] = $row["name"];
$data[$i]["tags"][$j]["color"] = $row["color"];
}
}
PS:这是一个伪代码,我们的查询和表格更复杂,但这基本上是我们问题的本质。
是否可以使用内部查询来实现,甚至更好,只需使用连接?
由于我们需要填充5个表,我们最终会为每个活动执行5个查询。
谢谢。
答案 0 :(得分:0)
确保{strong>活动表上的标记表只有JOIN
。
您的查询应该是这样的。
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
活动表的主键是id
并且每一行都是唯一的(即,对于任何给定的activity.id
,名称永远不会改变),然后JOIN是安全的,即使有没有标签。我们将至少返回N
行,其中N
是tag.activityId
中具有相应id
的{{1}}行的数量。
因此,在PHP中,您可以使用单个查询构建数组。
activity
因为活动表中的信息永远不会改变,所以我们唯一需要追加的是标记,我们通过检查循环中的$data = [];
foreach($result as $row) {
$tags = ["name" => $row["tagName"], "color" => $row["tagColor"]];
if (isset($data[$row["id"]])) {
$data[$row["id"]]["tags"][] = $tags;
} else {
$data[$row["id"]] = [
[
"id" => $row["id"],
"name" => $row["name"],
"tags" => [$tags],
],
];
}
}
来做。
所以从这个SQLFiddle你可以看到两个表的工作示例,其中isset($data[$row["id"]])
中有4行,activity
表中有6行。这给了我们总共6行。由于活动表中的一个ID没有任何标记,因此将其从结果集中排除。要获取包含0个代码的行,您可以使用tag
代替like this。
LEFT JOIN
这意味着我们为空标记行获取空值。所以我们可以修改PHP看起来像这样。
SELECT activity.id, activity.name,
tag.activityId AS tagId, tag.name AS tagName, tag.color AS tagColor
FROM activity
LEFT JOIN tag ON tag.activityId = activity.id;
因此,使用$data = [];
foreach($result as $row) {
$tags = empty($row["tagId"]) ?: ["name" => $row["tagName"], "color" => $row["tagColor"]];
if (isset($data[$row["id"]]) && $tags) {
$data[$row["id"]]["tags"][] = $tags;
} else {
$data[$row["id"]] = [
[
"id" => $row["id"],
"name" => $row["name"],
"tags" => $tags ? [$tags] : [],
],
];
}
}
的PHP的最终输出,以及SQLFiddle中的示例数据,应该看起来像这样。
"1": { "id": 1, "name": "foo", "tags": [ { "tagName": "tag-a", "tagColor": "red" }, { "tagName": "tag-b", "tagColor": "green" }, { "tagName": "tag-c", "tagColor": "blue" } ] }, "2": { "id": 2, "name": "bar", "tags": [ { "tagName": "tag-a", "tagColor": "orange" }, { "tagName": "tag-b", "tagColor": "red" } ] }, "3": { "id": 3, "name": "baz", "tags": [ { "tagName": "tag-a", "tagColor": "purple" } ] }, "4": { "id": 4, "name": "quix", "tags": [] } }