Лучший способ создать вложенный массив из таблиц: несколько запросов / циклов против одного стиля запроса / цикла
Скажем, у меня есть 2 таблицы, которые я могу "объединить" и представить в одном вложенном массиве.
Я брожу, что было бы лучшим способом сделать это, учитывая:
- эффективность
- передовая практика
- Компромисс между использованием БД и сервера
- что ты должен делать в реальной жизни
- тот же случай для 3, 4 или более таблиц, которые могут быть объединены таким образом
Вопрос о ЛЮБОЙ стороне сервера / реляционном БД.
2 простых способа, о которых я думал (если у вас есть другие, пожалуйста, предложите! Обратите внимание, я прошу простую SERVER-SIDE и RELATIONAL-DB, поэтому, пожалуйста, не тратьте свое время на объяснение, почему я не должен использовать этот вид БД, использовать MVC design и тд и тп...)
- 2 цикла, 5 простых запросов SELECT
- 1 цикл, 1 запрос "JOIN"
Я попытался привести простой и подробный пример, чтобы объяснить себя и лучше понять ваши ответы (хотя, как написать код и / или найти возможные ошибки, здесь не проблема, поэтому постарайтесь не фокусироваться на этом...)
SQL СКРИПТЫ ДЛЯ СОЗДАНИЯ И ВСТАВКИ ДАННЫХ В ТАБЛИЦЫ
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"
]
}
]
КОД ПСЕВДО НА 2 ПУТИ:
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
3 ответа
предварительный
Во-первых, спасибо, что приложили столько усилий для объяснения проблемы и для форматирования. Замечательно видеть кого-то, кто знает о том, что они делают, и о чем они спрашивают.
Но следует отметить, что это само по себе является ограничением: вы сосредоточены на идее, что это правильное решение, и что с небольшим исправлением или руководством это сработает. Это неверно. Поэтому я должен попросить вас отказаться от этого понятия, сделать большой шаг назад и рассмотреть (а) всю проблему и (б) мой ответ без этого понятия.
Контекст этого ответа:
все явные соображения, которые вы дали, которые очень важны, которые я не буду повторять
два наиболее важных из которых, что лучше всего практиковать и что я буду делать в реальной жизни
Этот ответ основан на стандартах, высшем порядке или системе отсчета наилучшей практики. Это то, что я делал в реальной жизни с 1990 года, а это означает, что с 1990 года у меня никогда не было необходимости писать такой код, как ваш. Это то, что коммерческий клиент / серверный мир делает или должен делать.
Эта проблема, все это проблемное пространство, становится общей проблемой. Я подробно расскажу здесь и, таким образом, отвечу на еще один вопрос SO. Поэтому он может содержать чуть больше деталей, которые вам требуются. Если это так, пожалуйста, прости это.
рассмотрение
База данных представляет собой серверный ресурс, которым пользуются многие пользователи. В онлайн-системе база данных постоянно меняется. Он содержит одну версию истины (в отличие от одного факта в одном месте, который является отдельной проблемой нормализации) каждого факта.
- Тот факт, что NONsqls у Микки Мауса не имеют серверной архитектуры, и что поэтому понятие сервера в таком программном обеспечении является ложным и вводящим в заблуждение, являются отдельными, но отмеченными моментами.
Насколько я понимаю, JSON и JSON-подобные структуры необходимы по "соображениям производительности", именно потому, что "сервер" не может, не может работать как сервер. Идея состоит в том, чтобы кэшировать данные на каждом (каждом) клиенте так, чтобы вы не извлекали их все время с "сервера".
Это открывает вонючую банку с червями. Если вы не спроектируете и не осуществите это должным образом, черви переполнят приложение, и зловоние убьет вас.
Такая реализация является грубым нарушением клиент-серверной архитектуры, которая допускает простой код с обеих сторон и соответствующее развертывание программных компонентов и компонентов данных, так что время внедрения небольшое и эффективность высокая.
Кроме того, такая реализация требует значительных усилий по реализации, и она является сложной, состоящей из множества частей. Каждая из этих частей должна быть соответствующим образом разработана.
Сеть и множество книг, написанных в этой предметной области, предоставляют выгребную яму методов, продаваемых на основе предполагаемой простоты; легкость; кто-может-делать-нибудь; бесплатное программное обеспечение, может-делать-нибудь; и т. д. Для этих предложений нет научной основы.
Не архитектура и не стандарт
Как видно, вы узнали, что эта рыночная мифология является мошеннической. Вы столкнулись с одной проблемой, один случай, когда этот совет неверен. Как только вы решите эту одну проблему, появится следующая проблема, которая вам пока не ясна. Понятия - это бесконечный набор проблем.
Я не буду перечислять все ложные представления, которые эти притворные эксперты (на самом деле, цирковые уроды, которые не знают технологии) продают. Я верю, что по мере того, как вы будете продвигаться по моему ответу, вы заметите, что одно за другим продаваемое понятие является ложным.
Две нижние строки:
Понятия нарушают стандарты архитектуры и дизайна, а именно архитектуру клиент / сервер; Открытая архитектура; Инженерные принципы; и в меньшей степени в этой конкретной проблеме, Принципы проектирования баз данных.
Что приводит к таким людям, как вы, которые пытаются делать честную работу, обманутые, обманутые, соблазненные, в реализации простых понятий, которые превращаются в массовые реализации. Реализации, которые никогда не будут работать, поэтому они требуют существенного постоянного обслуживания и в конечном итоге будут заменены оптом.
Архитектура
Нарушается главный принцип: никогда ничего не дублировать. В тот момент, когда у вас есть место, где данные дублируются (из-за кэширования или репликации или двух отдельных монолитных приложений и т. Д.), Вы создаете дубликат, который не синхронизируется в онлайн-ситуации. Поэтому принцип состоит в том, чтобы этого не делать.
- Несомненно, что для серьезного стороннего программного обеспечения, такого как инструмент для грубых отчетов, они могут кэшировать данные на сервере в клиенте. Но обратите внимание, что они потратили сотни человеко-лет на его правильное внедрение с должным учетом вышеизложенного. Ваш не такой кусок программного обеспечения.
Вместо того, чтобы давать лекцию о принципах, которые необходимо понять, или о зле и стоимости каждой ошибки, остальная часть этого ответа содержит запрашиваемую информацию о том, что вы будете делать в реальной жизни, используя правильный архитектурный метод (шаг выше наилучшей практики),
Архитектура 1
Не путай
- данные
который должен быть нормализован
с
- набор результатов
который, по определению, представляет собой уплощенное ("ненормализованное" не совсем правильное) представление данных.
Данные, учитывая, что они нормализованы, не будут содержать повторяющихся значений; повторяющиеся группы. Результирующий набор будет содержать повторяющиеся значения; повторяющиеся группы. Это пешеход.
Обратите внимание, что понятие "вложенные множества" (или "вложенные отношения"), широко распространяемое шизофрениками, основано именно на этой путанице.
В течение сорока пяти лет с момента появления РМ они не могли дифференцировать базовые отношения (для которых нормализация применяется) от производных отношений (для которых нормализация не применяется).
Два из уродов в настоящее время совершают нападение на определение первой нормальной формы. Это нападение на интеллект. Это (если принято) нормализует безумие. 1NF является основой других NF, и если это безумие будет принято, все NF будут повреждены, унижены, обесценены. В результате сама нормализация (редко определяемая в математических терминах, но ясно понимаемая специалистами как наука) будет серьезно повреждена, если не будет уничтожена.
Архитектура 2
Существует многовековой научный или инженерный принцип, согласно которому контент (данные) должен быть отделен от контроля (элементов программы). Это потому, что анализ; дизайн; и реализация двух совершенно разные. Этот принцип не менее важен в науке о программном обеспечении, где он имеет конкретную артикуляцию.
Чтобы сохранить это краткое (ха-ха), вместо разговора, я буду предполагать, что вы понимаете:
То, что существует научно обоснованная граница между данными и элементами программы. Смешивание их приводит к сложным объектам, которые подвержены ошибкам и трудны в обслуживании.
Неразбериха с этим принципом достигла масштабов эпидемии в мире ОО / ОРМ, последствия достигли огромных масштабов.
Только образованные профессионалы избегают этого безумия. В остальном, подавляющее большинство, они воспринимают это безумие как "нормальное" и проводят свою жизнь, решая проблемы, которых у нас просто нет.
Архитектурное превосходство, большая ценность данных, которые хранятся и представляются в табличной форме в соответствии с реляционной моделью доктора Э. Ф. Кодда. Что существуют конкретные правила для нормализации данных.
И что важно, вы можете определить, когда люди в сумасшедшем доме, которые пишут и продают книги, советуют нереляционные или антиреляционные методы.
Архитектура 3
Если вы кешируете данные на клиенте:
Кеш абсолютный минимум.
Это означает, что кешируются только данные, которые не изменяются в онлайн-среде. Это означает только таблицы ссылок и поиска, таблицы, которые заполняют классификаторы более высокого уровня, раскрывающиеся списки и т. Д.
валюта
Для каждой таблицы, которую вы кешируете, у вас должен быть метод (а) определения того, что кэшированные данные устарели по сравнению с Единой версией истины, существующей на сервере, и (б) ее обновления с сервера, (в) по каждому столу.
Как правило, это включает в себя фоновый процесс, который выполняется каждые (e) пять минут, который запрашивает обновленный MAX DateTime для каждой кэшированной таблицы на клиенте против DateTime на сервере, и, если он был изменен, обновляет таблицу и все ее дочерние таблицы, те, которые зависят от измененной таблицы.
Это, конечно, требует, чтобы у вас был
UpdatedDateTime
столбец на каждой таблице. Это не бремя, потому что это нужно для транзакций OLTP ACID в любом случае (если у вас есть реальная база данных, а не куча нестандартных файлов).
Что на самом деле означает, что никогда не копировать, бремя кодирования является непомерно высоким.
Архитектура 4
В субкоммерческом, несерверном мире я понимаю, что уроды советуют обратное (безумные люди всегда противоречат здравомыслию), кеширование "всего".
Это единственный способ, с помощью которого программы, подобные PusGresQl, созданные их когортами в одном и том же убежище, могут использоваться в многопользовательской системе, единственный путь, которым они могут распространять свой рак.
Вы всегда получаете то, за что платите: вы платите арахис, вы получаете обезьян; Вы платите ноль, вы получаете ноль.
Следствием архитектуры 3 является то, что если вы кешируете данные на клиенте, не кешируйте таблицы, которые часто меняются. Это таблицы транзакций и истории. Понятие кэширования таких таблиц или всех таблиц на клиенте полностью обанкротилось.
При подлинном развертывании клиент / сервер из-за использования применимых стандартов для каждого окна данных приложение должно запрашивать только те строки, которые необходимы для этой конкретной потребности в конкретный момент времени, на основе значений контекста или фильтра и т. Д. Приложение никогда не должно загружать всю таблицу.
Если тот же пользователь, использующий то же самое окно, проверил его содержимое, через 15 минут после первой проверки, данные будут на 15 минут устаревшими.
Для платформ freeware/shareware/vapourware, которые определяют себя отсутствием серверной архитектуры и, как следствие, тем, что производительность не существует, конечно, вы должны кэшировать больше, чем минимальные таблицы на клиенте.
Если вы сделаете это, вы должны принять во внимание все вышеперечисленное и правильно реализовать его, в противном случае ваше приложение будет сломано, и зловоние заставит пользователей искать ваше прекращение. Если есть более одного пользователя, они будут иметь ту же причину и скоро сформируют армию.
Архитектура 5
Теперь мы подошли к тому, как вы кешируете эти тщательно отобранные таблицы на клиенте.
Обратите внимание, что базы данных растут, они расширяются.
Если система сломана, произойдет сбой, она будет расти небольшими шагами и потребует больших усилий.
Если система будет даже небольшого успеха, она будет расти в геометрической прогрессии.
Если система (каждая база данных и приложение отдельно) спроектирована и реализована хорошо, изменения будут простыми, ошибок будет немного.
Поэтому все компоненты в приложении должны быть спроектированы надлежащим образом, чтобы соответствовать применимым стандартам, а база данных должна быть полностью нормализована. Это, в свою очередь, сводит к минимуму влияние изменений в базе данных, на приложение и наоборот.
Приложение будет состоять из простых, не сложных объектов, которые легко обслуживать и изменять.
Для данных, которые вы кэшируете на клиенте, вы будете использовать массивы некоторой формы: несколько экземпляров класса в платформе OO; DataWindows (TM, Google для него) или аналогичные в 4GL; простые массивы в PHP.
(За исключением. Обратите внимание, что то, что люди в таких ситуациях, как ваша, производят за один год, профессиональные провайдеры, такие как я, за одну неделю, используют коммерческую платформу SQL, коммерческий 4GL и соблюдают архитектуру и стандарты.)
Архитектура 6
Итак, давайте предположим, что вы понимаете все вышесказанное и цените его ценность, в частности, Архитектура 1 и 2.
- Если вы этого не сделаете, пожалуйста, остановитесь здесь и задайте вопросы, не переходите к следующему.
Теперь, когда мы создали полный контекст, мы можем решить суть вашей проблемы.
В этих массивах в приложении, с какой стати вы будете хранить плоские представления данных?
- и, следовательно, связываться и мучиться с проблемами
вместо хранения копий нормализованных таблиц?
Ответ
Никогда не дублируйте что-либо, что может быть получено. Это архитектурный принцип, не ограничивающийся нормализацией в базе данных.
Никогда ничего не объединяй.
Если вы это сделаете, вы будете создавать:
Дублирование данных и их масса на клиенте. Клиент будет не только толстым и медленным, он будет привязан к полу с балластом дублированных данных.
дополнительный код, который совершенно не нужен
сложность в этом коде
Хрупкий код, который постоянно должен меняться.
Это именно та проблема, которой вы страдаете, следствие того метода, который, как вы понимаете, интуитивно неверен, что должен быть лучший путь. Вы знаете, что это общая проблема.
Также обратите внимание, что метод (продаваемый яд), этот код, является для вас ментальным якорем. Посмотрите, как вы его отформатировали и представили так красиво: это важно для вас. Я не хочу сообщать вам обо всем этом.
- Какое нежелание легко преодолеть из-за вашего серьезного и откровенного отношения и знания того, что вы не изобрели этот метод, что вы последовали за "учителями", которые, как свидетельствует, совершенно не знают соответствующей науки, которые продают безумие; не-наука; бред, как "наука".
В каждом сегменте кода во время представления, как и когда требуется:
а. В коммерческом контексте Клиент / Сервер
Выполните запрос, который объединяет простые, нормализованные, не дублированные таблицы и извлекает только подходящие строки. Тем самым получая текущие значения данных. Пользователь никогда не видит устаревшие данные. Здесь часто используются представления (сглаженные представления нормализованных данных).б. В суб-коммерческом несерверном контексте
Создайте временный массив набора результатов и объедините простые, не дублированные массивы (копии кэшируемых таблиц) и заполните его только подходящими строками из исходных массивов. Валюта которого поддерживается фоновым процессом.Используйте ключи для формирования объединений между массивами, точно так же, как ключи используют для формирования объединений в реляционных таблицах в базе данных.
Уничтожьте эти компоненты, когда пользователь закроет окно.
Умная версия исключит массив набора результатов, объединит исходные массивы с помощью ключей и ограничит результат соответствующими строками.
В отличие от архитектурного безумия, вложенные массивы или вложенные наборы или JSON или JSON-подобные структуры просто не требуются. Это является следствием путаницы Принципа Архитектуры 1.
- Если вы решите использовать такие структуры, используйте их только для временных массивов наборов результатов.
Наконец, я верю, что этот дискурс демонстрирует, что n таблиц не является проблемой. Более важно то, что m уровней глубоко в иерархии данных, "вложение", не является проблемой.
Ответ 2
Теперь, когда я дал полный контекст (и не раньше), который устраняет последствия в вашем вопросе и делает его общим, базовым.
Вопрос о ЛЮБОЙ стороне сервера / реляционном БД. [Что лучше]:
2 цикла, 5 простых запросов SELECT
1 цикл, 1 запрос "JOIN"
Подробные примеры, которые вы привели, точно не описаны выше. Точные описания:
Ваш Вариант 1 2 цикла, каждый цикл для загрузки каждого массива 1 запрос одной таблицы SELECT на цикл (выполняется nxm раз... только самый внешний цикл - это одно выполнение)
Ваш вариант 2 1 Объединенный запрос SELECT выполняется один раз, за которым следуют 2 цикла, каждый цикл для загрузки каждого массива
Для коммерческих платформ SQL нет, потому что это не относится.
- Коммерческий сервер SQL - это механизм обработки множеств. Используйте один запрос с необходимыми объединениями, который возвращает набор результатов. Никогда не проходите по строкам, используя цикл, который сводит механизм обработки множеств к системе ISAM, существовавшей до 1970 года. Используйте View на сервере, поскольку он обеспечивает максимальную производительность, а код находится в одном месте.
Однако для некоммерческих несерверных платформ, где:
ваш "сервер" не является механизмом обработки множеств, т.е. он возвращает отдельные строки, поэтому вам нужно выбрать каждую строку и заполнить массив вручную или
ваш "сервер" не обеспечивает привязку клиент / сервер, т.е. на клиенте не предусмотрены средства для привязки входящего результирующего набора к получающему массиву, и поэтому вам нужно пошагово просмотреть возвращенный результирующий набор построчно и заполнить массив вручную,
в соответствии с вашим примером, ответ, с большим отрывом, ваш вариант 2.
Пожалуйста, внимательно рассмотрите и прокомментируйте или задайте вопросы.
Ответ на комментарий
Скажем, мне нужно напечатать этот json (или другую html-страницу) на каком-то STOUT (пример: http-ответ на: GET /allUsersPhoneNumbers. Это просто пример, чтобы уточнить, что я ожидаю получить), должен вернуть этот json. У меня есть функция PHP, которая получила эти 2 набора результатов (1). Теперь он должен напечатать этот JSON - как мне это сделать?. этот отчет может быть месячной зарплатой работника за целый год и т. д. так или иначе, мне нужно собрать эту информацию и представить ее в виде "JOIN"
Возможно, я не был достаточно ясен.
По сути, не используйте JSON. Если вам абсолютно не нужно. Что означает отправку в какую-либо систему, которая требует этого, что означает, что принимающая система и эта потребность очень, очень глупы.
Убедитесь, что ваша система не предъявляет такие требования к другим.
Держите ваши данные в норме. Как в базе данных, так и в любых элементах программы, которые вы пишете. Это означает (в этом примере) использовать один SELECT для таблицы или массива. Это для целей загрузки, так что вы можете обращаться к ним и проверять их в любой точке программы.
Когда вам нужно объединение, понимайте, что это:
- набор результатов; производное отношение; вид
- поэтому временный, он существует на время выполнения этого элемента, только
а. Для таблиц, соединяйте их обычным способом, используя клавиши. Один запрос, объединяющий две (или более) таблицы.
б. Для массивов объединяйте массивы в программе так же, как вы соединяете таблицы в базе данных с помощью ключей.
Для приведенного вами примера, который является ответом на какой-то запрос, сначала следует понять, что это категория [4], а затем выполнить его.
Почему даже рассмотреть JSON???
Какое отношение имеет JSON к этому???JSON недопонимают, и люди заинтересованы в вау-факторе. Это решение ищет проблему. Если у вас нет этой проблемы, она не имеет значения. Проверьте эти две ссылки:
Вертолет - Что такое JSON
Stackru - Что такое JSONТеперь, если вы это понимаете, это в основном для входящих каналов. Никогда для исходящих. Кроме того, он требует синтаксического анализа, деконструкции и т. Д. Перед использованием.
Отзыв:
мне нужно собрать эту информацию и представить ее в формате "JOIN"
Да. Это пешеход. Регистрация не означает JSONed.
В вашем примере получатель ожидает плоское представление (например, электронную таблицу) со всеми заполненными ячейками, и да, для пользователей с более чем одним PhoneNumber их пользовательские данные будут повторяться во второй и последующих строках набора результатов. Для любого вида print,
например. для отладки я хочу плоский вид. Это просто:
SELECT ... FROM Person JOIN PhoneNumber
И верни это. Или, если вы выполняете запрос от массивов, присоединитесь к массивам Person и PhoneNumber, для которых может потребоваться временный массив набора результатов, и верните его.
пожалуйста, не говорите мне, что вы должны получать только 1 пользователя за раз и т. д.
Правильный. Если кто-то говорит вам вернуться к процедурной обработке (т. Е. Строка за строкой в цикле WHILE), когда механизм или ваша программа выполняет обработку набора (т. Е. Обрабатывает весь набор в одной команде), это помечает их как идиота. Прекратите слушать их полностью.
Я уже говорил, ваш вариант 2 правильный, вариант 1 неправильный. Это касается GET или SELECT.
С другой стороны, для языков программирования, которые не имеют возможности обработки множеств (т. Е. Не могут печатать / устанавливать / проверять массив в одной команде), или для "серверов", которые не обеспечивают привязку массива на стороне клиента, у вас есть чтобы записать циклы, один цикл на глубину иерархии данных (в вашем примере два цикла, один для Person и один для PhoneNumber для каждого пользователя).
- Вы должны сделать это, чтобы проанализировать входящий объект JSON.
- Вы должны сделать это, чтобы загрузить каждый массив из результирующего набора, который возвращается в вашем варианте 2.
- Вы должны сделать это, чтобы напечатать каждый массив из результирующего набора, который возвращается в вашем варианте 2.
Ответ на комментарий 2
Я должен вернуть результат, представленный во вложенной версии (скажем, я печатаю отчет на страницу), json был просто примером такого представления.
Я не думаю, что вы понимаете причины и выводы, которые я привел в этом ответе.
- Для печати и отображения никогда не вкладывайте. Напечатайте уплощенное представление, строки, возвращаемые из SELECT для Варианта 2. Это то, что мы делали, когда печатали или отображали данные Относительно, в течение 31 года. Его легче читать, отлаживать, искать, находить, складывать, скреплять, калечить. Вы не можете ничего сделать с вложенным массивом, кроме как посмотреть на него и сказать, что это интересно.
Я давал вам указания, чтобы вы могли написать необходимый код, но это не работает. Похоже, я должен написать код для вас.
Код
Предостережение
Я бы предпочел взять ваш код и изменить его, но на самом деле, глядя на ваш код, он не очень хорошо написан или структурирован, он не может быть разумно изменен. Во-вторых, если я воспользуюсь этим, это будет плохой учебный инструмент. Поэтому мне придется дать вам свежий, чистый код, иначе вы не научитесь правильным методам.
Эти примеры кода следуют моему совету, поэтому я не собираюсь повторяться. И это далеко за пределы первоначального вопроса.
Ваш запрос, используя ваш вариант 2. Один SELECT выполняется один раз. Далее следует один цикл. Который вы можете "нарядить", если хотите.
Как правило, рекомендуется собирать необходимые данные за как можно меньшее количество поездок в базу данных, а затем сопоставлять данные с соответствующими объектами. (Вариант 2)
Но, чтобы ответить на ваш вопрос, я бы спросил себя, каков вариант использования ваших данных. Если вы точно знаете, что вам понадобятся данные о вашем лице и номере телефона, я бы сказал, что второй способ - ваш лучший вариант.
Однако вариант 1 также может иметь свой вариант использования, когда присоединяемые данные являются необязательными. Одним из примеров этого может быть то, что в пользовательском интерфейсе у вас есть таблица всех ваших людей, и если пользователь хочет видеть номер телефона конкретного человека, которого он должен нажать на этого человека. Тогда было бы приемлемо "лениво загрузить" все телефонные номера.
Это общая проблема, особенно если вы создаете WebAPI, преобразование этих наборов таблиц во вложенные массивы является большой проблемой.
Я всегда выбираю для вас второй вариант (хотя и в несколько ином методе), потому что первый - наихудший из возможных способов сделать это... Одна вещь, которую я узнал из своего опыта, - это никогда не выполнять запросы внутри цикла, а это пустая трата вызовов БД. ну ты знаешь что я пытаюсь сказать.
Несмотря на то, что я не принимаю все, что сказал PerformanceDBA, мне нужно указать два важных момента: 1. Не иметь дублирующихся данных. 2. Получать только те данные, которые вам нужны.
Единственная проблема, которую я вижу в присоединении к таблице, заключается в том, что мы в конечном итоге дублируем множество данных, например, данные о присоединении и таблицы phoneNumber. В конечном итоге мы дублируем каждого человека для каждого его номера телефона, для двух таблиц с несколькими сотнями строки это хорошо, представьте, что нам нужно объединить 5 таблиц с тысячами строк, это огромно... Итак, вот мое решение:
Запрос:
SELECT id, fullName From Person;
SELECT personId, phoneNumber FROM phoneNumbers
WHERE personId IN (SELECT id From Person);
Таким образом, я попал в таблицы в своем наборе результатов, теперь я назначаю Table[0] своему списку Person и использую 2 цикла, чтобы поместить правильные phoneNumbers в нужного человека...
Код:
personList = ConvertToEntity<List<Person>>(dataset.Table[0]);
pnoList = ConvertToEntity<List<PhoneNumber>>(dataset.Table[1]);
foreach (person in personList) {
foreach (pno in pnoList) {
if(pno.PersonId = person.Id)
person.PhoneNumer.Add(pno)
}
}
Я думаю, что вышеописанный метод уменьшает количество дублирований и дает мне только то, что я хотел, если есть недостатки этого метода, пожалуйста, дайте мне знать... и спасибо, что задали такие вопросы...