Лучший способ создания вложенного массива из таблиц: несколько запросов / циклов VS single query / loop style

Скажем, у меня есть 2 таблицы, которые я могу «объединить» и представить в одном вложенном массиве.

Я блуждаю, что было бы лучшим способом сделать это, учитывая:

  • эффективность
  • передовая практика
  • Комбинация использования БД / серверной стороны
  • что вы должны делать в реальной жизни
  • тот же случай для 3, 4 или более таблиц, которые могут быть «слиты» таким образом

Речь идет о ЛЮБОЙ стороне сервера / реляционной-db.

2 простых способа, о которых я думал (если у вас есть другие, пожалуйста, сообщите!). Я прошу простую базу SERVER-SIDE и RELATIONAL-DB , поэтому, пожалуйста, не теряйте время, объясняя, почему я не должен использовать этот вид DB, используйте проект MVC и т. Д. И т. Д. …):

  1. 2 цикла, 5 простых запросов «SELECT»
  2. 1, 1 запрос «JOIN»

Я попытался привести простой и подробный пример, чтобы объяснить себя и лучше понять ваши ответы (хотя, как написать код и / или найти возможные ошибки, здесь не проблема, поэтому постарайтесь не сосредоточиться на этом. .)

SQL SCRIPTS ДЛЯ СОЗДАНИЯ И ВСТАВКИ ДАННЫХ В ТАБЛИЦЫ

CREATE TABLE persons ( id int NOT NULL AUTO_INCREMENT, fullName varchar(255), PRIMARY KEY (id) ); INSERT INTO persons (fullName) VALUES ('Alice'), ('Bob'), ('Carl'), ('Dan'); CREATE TABLE phoneNumbers ( id int NOT NULL AUTO_INCREMENT, personId int, phoneNumber varchar(255), PRIMARY KEY (id) ); INSERT INTO phoneNumbers (personId, phoneNumber) VALUES ( 1, '123-456'), ( 1, '234-567'), (1, '345-678'), (2, '456-789'), (2, '567-890'), (3, '678-901'), (4, '789-012'); 

JSON ПРЕДСТАВЛЕНИЕ ТАБЛИЦ В ПОСЛЕ Я «СЛУЧАЙ» ИХ:

 [ { "id": 1, "fullName": "Alice", "phoneNumbers": [ "123-456", "234-567", "345-678" ] }, { "id": 2, "fullName": "Bob", "phoneNumbers": [ "456-789", "567-890" ] }, { "id": 3, "fullName": "Carl", "phoneNumbers": [ "678-901" ] }, { "id": 4, "fullName": "Dan", "phoneNumbers": [ "789-012" ] } ] 

PSEUDO CODE FOR 2 WAYS:

1.

 query: "SELECT id, fullName FROM persons" personList = new List<Person>() foreach row x in query result: current = new Person(x.fullName) "SELECT phoneNumber FROM phoneNumbers WHERE personId = x.id" foreach row y in query result: current.phoneNumbers.Push(y.phoneNumber) personList.Push(current) print personList 

2.

 query: "SELECT persons.id, fullName, phoneNumber FROM persons LEFT JOIN phoneNumbers ON persons.id = phoneNumbers.personId" personList = new List<Person>() current = null previouseId = null foreach row x in query result: if ( x.id != previouseId ) if ( current != null ) personList.Push(current) current = null current = new Person(x.fullName) current.phoneNumbers.Push(x.phoneNumber) print personList 

РЕАЛИЗАЦИЯ КОДА В PHP / MYSQL:

1.

 /* get all persons */ $result = mysql_query("SELECT id, fullName FROM persons"); $personsArray = array(); //Create an array //loop all persons while ($row = mysql_fetch_assoc($result)) { //add new person $current = array(); $current['id'] = $row['id']; $current['fullName'] = $row['fullName']; /* add all person phone-numbers */ $id = $current['id']; $sub_result = mysql_query("SELECT phoneNumber FROM phoneNumbers WHERE personId = {$id}"); $phoneNumbers = array(); while ($sub_row = mysql_fetch_assoc($sub_result)) { $phoneNumbers[] = $sub_row['phoneNumber']); } //add phoneNumbers array to person $current['phoneNumbers'] = $phoneNumbers; //add person to final result array $personsArray[] = $current; } echo json_encode($personsArray); 

2.

 /* get all persons and their phone-numbers in a single query */ $sql = "SELECT persons.id, fullName, phoneNumber FROM persons LEFT JOIN phoneNumbers ON persons.id = phoneNumbers.personId"; $result = mysql_query($sql); $personsArray = array(); /* init temp vars to save current person's data */ $current = null; $previouseId = null; $phoneNumbers = array(); while ($row = mysql_fetch_assoc($result)) { /* if the current id is different from the previous id: you've got to a new person. save the previous person (if such exists), and create a new one */ if ($row['id'] != $previouseId ) { // in the first iteration, // current (previous person) is null, // don't add it if ( !is_null($current) ) { $current['phoneNumbers'] = $phoneNumbers; $personsArray[] = $current; $current = null; $previouseId = null; $phoneNumbers = array(); } // create a new person $current = array(); $current['id'] = $row['id']; $current['fullName'] = $row['fullName']; // set current as previous id $previouseId = $current['id']; } // you always add the phone-number // to the current phone-number list $phoneNumbers[] = $row['phoneNumber']; } } // don't forget to add the last person (saved in "current") if (!is_null($current)) $personsArray[] = $current); echo json_encode($personsArray); 

PS эта ссылка является примером другого вопроса здесь, где я попытался предложить второй способ: таблицы для одиночного json

В общем, лучше всего захватить нужные вам данные за несколько поездок в базу данных, а затем сопоставить данные с соответствующими объектами. (Вариант 2)

Но, чтобы ответить на ваш вопрос, я хотел бы спросить себя, что такое прецедент для ваших данных. Если вы точно знаете, что вам понадобится ваш человек и данные вашего номера телефона, я бы сказал, что второй способ – ваш лучший вариант.

Однако вариант один может также иметь свой прецедент, когда объединенные данные являются необязательными. Одним из примеров этого может быть то, что в пользовательском интерфейсе у вас есть таблица всех ваших людей, и если пользователь хочет видеть номер телефона для определенного человека, нужно нажать на этого человека. Тогда было бы приемлемо «ленить» все телефонные номера.