首页 > 解决方案 > 如何使用 CodeIngiter 将连接表查询结果调整为所需的 JSON 格式

问题描述

假设我们有一张桌子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格式。

任何想法将不胜感激。

对不起,我的英语不好。

标签: mysqljsoncodeigniter

解决方案


首先,您无法通过一个查询phone在每个内部检索多个所需的结果。person

现在,person如果有大量数据,在循环内运行查询将极大地影响脚本的性能。这样,首先,您需要执行查询以获取所有人员(例如n人员)。然后你必须再次循环所有人n以获取他们各自的电话。因此,您需要在$persons循环n时间内运行以下内容:

SELECT * FROM phone WHERE person_id = [$person_id]

因此,您需要以这种方式执行n+1查询。

为了克服这个n+1查询问题,我们可以应用一种称为 as 的方法eager loading。在这里,您还需要执行第一个查询来检索所有人员,然后编写一个查询来获取属于这些检索人员的所有电话:

SELECT * FROM person 

结果($人):

id      name
5       John
10      Bob
20      Jenna

SELECT * FROM phone WHERE person_id IN (5,10,20)

结果($电话):

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


推荐阅读