Php 在单个查询中填充一对多的结果
我有两个表:Php 在单个查询中填充一对多的结果,php,mysql,Php,Mysql,我有两个表:activity和tag。一个活动有许多标记。我需要优化我们当前的设置,在这里我们找到表中的所有活动,然后迭代每个活动以找到所有标记。最后,我们将内容作为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
activity
和tag
。一个活动
有许多标记
。我需要优化我们当前的设置,在这里我们找到表中的所有活动,然后迭代每个活动以找到所有标记。最后,我们将内容作为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"];
}
}
$result=mysqli\u查询(“
选择'id','name`
从`活动`
");
$data=array();
对于($i=0;$iSure justJOIN
activity表上的标记表
您的查询应该如下所示
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
活动表的主键是id
,并且每一行都是唯一的(即任何给定的activity.id
的名称都不会更改),则即使没有标记,联接也是安全的。我们将返回至少N
行,其中N
是tag.activityId
行的数量,这些行在activity
中具有相应的id
因此,在PHP中,您可以用这样一个查询构建数组
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
因为活动表中的信息永远不会改变,所以我们只需要附加标记,我们通过在循环中检查isset($data[$row[“id”]])
来完成
因此,从这里您可以看到两个表的工作示例,其中活动中有4行,而标记表中有6行。这总共给了我们6行。由于活动表中的一个ID没有任何标记,因此它被从结果集中排除。要返回带有0个标记的行,可以使用左连接
这意味着空标记行的值为空。所以我们可以修改PHP,使其看起来像这样
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
因此,使用json_encode
从PHP输出的最终结果,以及SQLFIDLE中的示例数据,应该如下所示
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
"1": {
“id”:1,
“名称”:“foo”,
“标签”:[
{
“标记名”:“标记a”,
“tagColor”:“红色”
},
{
“标记名”:“标记b”,
“标记颜色”:“绿色”
},
{
“标记名”:“标记c”,
“tagColor”:“蓝色”
}
]
},
"2": {
“id”:2,
“名称”:“酒吧”,
“标签”:[
{
“标记名”:“标记a”,
“tagColor”:“橙色”
},
{
“标记名”:“标记b”,
“tagColor”:“红色”
}
]
},
"3": {
“id”:3,
“名称”:“baz”,
“标签”:[
{
“标记名”:“标记a”,
“tagColor”:“紫色”
}
]
},
"4": {
“id”:4,
“名称”:“quix”,
“标签”:[]
}
}
当然,只需加入活动
表上的标记表即可
您的查询应该如下所示
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
活动表的主键是id
,并且每一行都是唯一的(即任何给定的activity.id
的名称都不会更改),则即使没有标记,联接也是安全的。我们将返回至少N
行,其中N
是tag.activityId
行的数量,这些行在activity
中具有相应的id
因此,在PHP中,您可以用这样一个查询构建数组
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
因为活动表中的信息永远不会改变,所以我们只需要附加标记,我们通过在循环中检查isset($data[$row[“id”]])
来完成
因此,从这里您可以看到两个表的工作示例,其中活动中有4行,而标记表中有6行。这总共给了我们6行。由于活动表中的一个ID没有任何标记,因此它被从结果集中排除。要返回带有0个标记的行,可以使用左连接
这意味着空标记行的值为空。所以我们可以修改PHP,使其看起来像这样
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
因此,使用json_encode
从PHP输出的最终结果,以及SQLFIDLE中的示例数据,应该如下所示
SELECT activity.id, activity.name, tag.name AS tagName, tag.color AS tagColor
FROM activity
JOIN tag ON tag.activityId = activity.id;
$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],
],
];
}
}
$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] : [],
],
];
}
}
"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": []
}
}
"1": {
“id”:1,
“名称”:“foo”,
“标签”:[
{
“标记名”:“标记a”,
“tagColor”:“红色”
},
{
“标记名”:“标记b”,
“标记颜色”:“绿色”
},
{
“标记名”:“标记c”,
“tagColor”:“蓝色”
}
]
},
"2": {
“id”:2,
“名称”:“酒吧”,
“标签”:[
{
“标记名”:“标记a”,
“tagColor”:“橙色”
},
{
“标记名”:“标记b”,
“tagColor”:“红色”
}
]
},
"3": {
“id”:3,
“名称”:“baz”,
“标签”:[
{
“标记名”:“标记a”,
“tagColor”:“紫色”
}
]
},
"4": {
“id”:4,
“名称”:“quix”,
“标签”:[]
}
}
谢谢@Sherif,但是我忘了提到我需要通过activity.id
对表进行分组,因为我要加入其他几个表。在这种情况下,它不起作用。为什么它不起作用呢?如果activity.id
是一个PK,那么它应该对这个用例没有影响。包括可疑的groupby
子句和您声称它不起作用的模式,我很乐意向您展示如何使它起作用。@例如,Serif,我有一个材料表,我需要知道我有多少材料用于单个活动,所以在我的选择器中,我放置了一个计数(material.activityId)
,这样就行了