Как обрабатывать древовидные структуры, возвращаемые из SQL-запроса с использованием PHP? - PullRequest
0 голосов
/ 31 января 2011

Это «теоретический» вопрос.

У меня проблемы с определением вопроса, поэтому, пожалуйста, потерпите меня.

Если у вас есть несколько связанных таблиц в базе данных, например,таблица, в которой хранятся «пользователи», и таблица, в которой хранятся «телефоны»

и «телефоны», и «пользователи» имеют столбец с именем «user_id»

select user_id,name,phone from users left outer join phones on phones.user_id = users.user_id;

, который запрос предоставит мнестроки всех пользователей, независимо от того, есть у них телефон или нет.

Если у пользователя несколько телефонов, его имя будет возвращено в 2 ряда, как и ожидалось.

columns=>|user_id|name|phone|
row0 = > | 0 |fred|NULL|
row1 = > | 1 |paul|tlf1|
row2 = > | 1 |paul|tlf2|

имя "paul""в приведенном выше случае необходим дубликат, который, по мнению RDMS, вовсе не является дубликатом!Затем он будет обрабатываться некоторым языком сценариев на стороне сервера, например php.

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

ps, если вы решили опубликовать примеры, опубликуйте их для php, mysql, sqlite, если это возможно.

edit:

Спасибо за предоставленные ответы, каждый ответ интерпретировал вопрос по-своему, и, как таковой, он отличается и корректен по-своему.

Я пришел к выводу, что еслиПоездки туда и обратно обходятся дорого, это будет наилучшим способом наряду с решением Якоба Нильссона-Эле, которое подходит для теоретического вопроса.

Если поездки туда и обратно дешевы, я сделаю отдельные выборки для телефонов и пользователей, как 9000Предполагается, что если мне нужно будет показать один телефон для каждого пользователя, я дам телефонам основной столбец и присоединю его к пользователю, выбрав, как правильно предлагает Олли Джонс.

, хотя для реальных приложений яИспользуя ответ 9000, я думаю, что для этого нереального вопроса решение Якоба Нильссона-Эле является наиболее подходящим.

Ответы [ 4 ]

1 голос
/ 31 января 2011

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

Тривиальное ORM не является решением.

Существуют технологии отображения ORM, такие как спящий режим, однако они плохо масштабируются. IME, лучшее решение - использовать фабричный шаблон для правильного управления отображением.

1 голос
/ 31 января 2011

Вы не можете легко получить древовидную структуру из СУБД, только структуру таблицы. И вы хотите дерево: [(user1, (phone1, phone2)), (user2, (phone2, phone3))...]. Тем не менее, вы можете оптимизировать работу с разными целями.

  • Поездки туда и обратно обходятся дороже, чем отправка дополнительной информации: используйте свое текущее решение. Он выбирает имя пользователя несколько раз, но у вас есть только один круговой вызов на всю телефонную книгу. Может иметь смысл, если ваш перегруженный хост MySQL находится на расстоянии 1000 миль.

  • Отправка дополнительной информации обходится дороже, чем поездки туда или обратно, или вы хотите большей ясности: как подсказывает @ martinho-fernandes, извлекайте только идентификаторы пользователей с телефонами, а затем извлекайте данные пользователей в другом запросе. Я бы придерживался этого подхода, если только ваши пользовательские данные не являются коротким именем пользователя. С SQLite я всегда буду придерживаться его только ради ясности.

1 голос
/ 31 января 2011

В этом случае, вероятно, я бы сделал в PHP использование userId в массиве PHP, а затем использовал его для постоянного обновления пользователей

Очень простой пример будет

$result = mysql_query('select user_id,name,phone from users left outer join phones on phones.user_id = users.user_id;');
$users = Array();
while($row = mysql_fetch_assoc($result)) {
   $uid =$row['user_id'];
   if(!array_key_exists($uid, $users)) {
      $users[$uid] = Array('name' => $row['name'], 'phones' => Array());
   }
   $users[$uid]['phones'][] = $row['phone']; 
}

Конечно, в зависимости от вашего стиля программирования и сложности пользовательских данных, вы можете определить класс пользователя или что-то еще и заполнить данные, но это принципиально, как я бы это сделал.

1 голос
/ 31 января 2011

Ваша модель данных позволяет пользователю иметь 0, 1 или более телефонов.

Вы можете заставить свою базу данных возвращать либо 0, либо 1 телефонный номер для каждого пользователя, используя неприятный хак, например, выбирая наименьший номер телефона. (MIN (телефон) ... GROUP BY пользователя). Но численное сравнение телефонных номеров имеет мало смысла.

Ваша проблема двусмысленности (какой из нескольких телефонных номеров) указывает на проблему в вашей модели модели данных. Взгляните, если хотите, на некоторые распространенные приложения телефонного справочника. Приложение быстрого набора на мобильном телефоне является хорошим примером. В основном они предлагают способы ввода нескольких телефонных номеров, но у них всегда есть концепция основного номера телефона.

Если вы добавите в свою таблицу телефона столбец с указанием приоритета номера и сделаете его частью своего первичного (уникального) ключа, и объявите, что приоритет = 1 означает основной номер пользователя, ваше приложение больше не будет иметь эту неоднозначную проблему .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...