如何使用CodeIngiter以所需的JSON格式调整联接表查询结果

时间:2018-06-25 07:34:52

标签: mysql json codeigniter

假设我们有表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格式。

任何想法都会受到赞赏。

对不起,我的英语不好。

1 个答案:

答案 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包含格式化的所需输出。