假设我们有表person
和表phone
,它们之间的关系是一对多的。
我需要通过一个查询来检索类似结果。
[
{
name:"abc",
lname:"def",
phones:[
{
dial_code="+1",
number:"12345667"
},
{
dial_code="+1",
number:"12345667"
}
]
},
{
name:"xyz",
lname:"lmn",
phones[
{
dial_code="+2",
number:"2643525"
}
]
},
{...}
]
我可以通过多个查询来做到这一点,例如先获取所有persons
,然后一个一个地获取它们的phones
,但我认为它是如此奇怪,需要大量时间并降低性能。如果我通过加入表来获取所有数据,那将不会是这种JSON
格式。
任何想法都会受到赞赏。
对不起,我的英语不好。
答案 0 :(得分:1)
首先,您无法通过单个查询在每个phone
中包含多个person
来检索所需的结果。
现在,如果有大量数据,则在person
循环内运行查询将极大地影响脚本的性能。这样,首先,您需要执行查询以获取所有人(例如n
个人)。然后,您必须再次循环所有n
个人以获取他们各自的电话。
因此,您需要在$persons
个循环n
内运行以下操作:
SELECT * FROM phone WHERE person_id = [$person_id]
因此,您需要以这种方式执行n+1
个查询。
为克服此n+1
查询问题,我们可以应用一种称为eager loading
的方法。在这里,您还需要执行第一个查询以检索所有人,然后编写查询以获取属于那些检索人的所有电话:
SELECT * FROM person
结果($人):
id name
5 John
10 Bob
20 Jenna
SELECT * FROM phone WHERE person_id IN (5,10,20)
结果($ phones):
id person_id dial_code number
1 5 +2 12345
2 10 +1 12312
3 20 +1 98765
现在,我们将这两个结果结合在PHP脚本中以生成所需的数组。这样,我们只编写了两个查询,而不是n+1
个查询。
您可以编写如下所示的PHP脚本来组合两个结果集:
// Create an array of phones with person_id as key
$phones_with_person_id_as_key = [];
foreach($phones as $key => $phone) {
$phones_with_person_id_as_key[$phone->person_id][$key] = $phone;
}
// Loop $persons array and add phones to person object
foreach($persons as $key => $person) {
// create phones key and add data
if (!empty($phones_with_person_id_as_key[$person->id])) {
$person->phones = $phones_with_person_id_as_key[$person->id];
}
else {
$person->phones = [];
}
}
现在$persons
包含格式化的所需输出。