В дополнение к Fesor:
Язык вы не указали, поэтому велосипед на PHP
// описание таблиц
$tableMap = array();
// $postsFields и $usersFields - это описание таблиц - в каком точно порядке
// поля
$tableMap['posts'] = array( // описание таблицы `posts`
'fields' => array('postid', 'title', 'post', 'date', 'userid'), // перечисление колонок
'primary' => 'postid', // primary ключ, для упрощения - несоставной
'relations' => array( // внешние ключи
'fk_userid' => array('userid', 'users', 'userid'), // ключ на таблицу `users` по полю `userid`
),
);
$tableMap['users'] = array( // описание таблицы `users`
'fields' => array('userid', 'username', 'usermail'), // перечисление колонок
'primary' => 'userid', // primary ключ, для упрощения - несоставной
'relations' => array( // внешние ключи
),
);
// $posts и $users - это два хранилища сущностей
$posts = array();
$users = array();
// $resultSet = это имитация результата выборки по запросу
// select
// p.postid, p.title, p.post, p.date, p.userid,
// u.userid, u.username, u.usermail
// from posts p
// join users u on p.userid = u.userid
// -- все колонки в этом запросе обязаны следовать в том же порядке, что и в описании таблиц $postsFields и $usersFields
$resulSet = array(
array(1,'post1_title','post1_content', '2013-10-16', 1, 1, 'login1', 'login1@domain'),
array(2,'post2_title','post2_content', '2013-10-16', 1, 1, 'login1', 'login1@domain'),
array(3,'post3_title','post3_content', '2013-10-16', 2, 2, 'login2', 'login2@domain'),
array(4,'post4_title','post4_content', '2013-10-16', 3, 3, 'login3', 'login3@domain'),
array(5,'post5_title','post5_content', '2013-10-16', 3, 3, 'login3', 'login3@domain'),
array(6,'post6_title','post6_content', '2013-10-16', 4, 4, 'login4', 'login4@domain'),
);
// теперь - перебор результатов выборки, составление сущностей с учётом повторения
foreach($resulSet as $row) {
reset($row);
// выбор из строки результата всех значений, относящихся к `posts`
$post = array();
foreach($tableMap['posts']['fields'] as $key) {
$post[$key] = current($row);
next($row);
}
// сохранение сущности в хранилище, если ещё не было сохранено
$pk = $post[$tableMap['posts']['primary']];
if (!isset($posts[$pk])) {
$posts[$pk] = $post;
}
// выбор из строки результата всех значений, относящихся к `users`
$user = array();
foreach($tableMap['users']['fields'] as $key) {
$user[$key] = current($row);
next($row);
}
// сохранение сущности в хранилище, если ещё не было сохранено
$pk = $user[$tableMap['users']['primary']];
if (!isset($users[$pk])) {
$users[$pk] = $user;
}
}
// последнее - составление массива с нужной структурой
$collection = array();
$index = 0;
foreach($posts as $post) {
$collection[$index] = $post;
// здесь надо воспользоваться $tableMap['posts']['relations']['fk_userid'], но мне лень
$fkUser = $post['userid'];
//echo '$fkUser=',$fkUser,PHP_EOL;
$collection[$index]['user'] = $users[$fkUser];
$index++;
}
var_export($collection);