(анекдот) Я спросил одного кадровика, почему все непременно требуют высшего образования. Он ответил: - Чтобы была гарантия, что человек в состоянии пяти лет бесплатно заниматься неинтересной ему фигнёй.
<?php
$propelQuery = PostsQuery::create()
->joinWith('users') // join c включением джойненой таблицы в SELECT ...
;
$propelCollection = $propelQuery->find();
$result = array(); $index = 0;
foreach($propelCollection as $post) {
$result[$index] = $post->toArray();
$result[$index]['user'] = $post->getUserss()->toArray();
$index++;
}
var_export($result);
// описание таблиц
$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);
$evalResult = @eval('$result = (bool)(1<2);');
$evalResult = null если выражение выполнилось
$evalResult = false если не выполнилось
CREATE TABLE POST (
ID DECIMAL(20,0), -- AUTOINCREMENT
CONTENT VARCHAR2(1024)
);
CREATE TABLE TAG (
ID DECIMAL(20,0), -- AUTOINCREMENT
TAG VARCHAR2(100)
);
CREATE TABLE POST_TAG (
POST_ID DECIMAL(20,0),
TAG_ID DECIMAL(20,0)
);
-- FOREIGN KEY FK_POST_TAG_POST ON POST(ID);
-- FOREIGN KEY FK_POST_TAG_TAG ON TAG(ID);
CREATE UNIQUE INDEX UQ_POST ON POST(ID);
CREATE UNIQUE INDEX UQ_TAG ON TAG(ID);
CREATE INDEX IDX_POST_TAG ON POST_TAG(POST_ID, TAG_ID);
CREATE INDEX IDX_POST_TAG_R ON POST_TAG(TAG_ID, POST_ID);
INSERT INTO TAG(ID, TAG) VALUES(1, 'foo');
INSERT INTO TAG(ID, TAG) VALUES(2, 'boo');
INSERT INTO TAG(ID, TAG) VALUES(3, 'goo');
INSERT INTO TAG(ID, TAG) VALUES(4, 'doo');
INSERT INTO TAG(ID, TAG) VALUES(5, 'too');
INSERT INTO POST(ID, CONTENT) VALUES(1, '...');
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(1, 1 /* foo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(1, 2 /* boo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(1, 3 /* goo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(1, 4 /* doo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(1, 5 /* too */);
INSERT INTO POST(ID, CONTENT) VALUES(2, '...');
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(2, 2 /* boo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(2, 3 /* goo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(2, 5 /* too */);
INSERT INTO POST(ID, CONTENT) VALUES(3, '...');
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(3, 1 /* foo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(3, 5 /* too */);
INSERT INTO POST(ID, CONTENT) VALUES(4, '...');
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(4, 4 /* doo */);
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(4, 5 /* too */);
INSERT INTO POST(ID, CONTENT) VALUES(5, '...');
INSERT INTO POST_TAG(POST_ID, TAG_ID) VALUES(5, 5 /* too */);
SELECT POST.ID, TAG.TAG
FROM POST, TAG, POST_TAG
WHERE POST.ID = POST_TAG.POST_ID AND TAG.ID = POST_TAG.TAG_ID
ORDER BY POST.ID, TAG.ID;
SELECT DISTINCT ID, POST_TAG_COUNT, POST_TAGS_MATCHED_COUNT, POST_TAG_COUNT - POST_TAGS_MATCHED_COUNT POST_TAGS_EXTRA
FROM (
SELECT
POST.ID,
( -- количество тегов всего
SELECT COUNT(POST_TAG.TAG_ID) CNT
FROM POST_TAG
WHERE POST_TAG.POST_ID = POST.ID
) POST_TAG_COUNT,
( -- количество найденных по точному совпадению
SELECT COUNT(POST_TAG.TAG_ID) CNT
FROM POST_TAG
JOIN TAG ON POST_TAG.TAG_ID = TAG.ID
WHERE TAG.TAG IN ('boo', 'too') AND POST_TAG.POST_ID = POST.ID
) POST_TAGS_MATCHED_COUNT
FROM POST
JOIN POST_TAG ON POST_TAG.POST_ID = POST.ID
JOIN TAG ON TAG.ID = POST_TAG.TAG_ID
WHERE TAG.TAG IN ('boo', 'too')
)
WHERE POST_TAGS_MATCHED_COUNT > 0
ORDER BY POST_TAGS_MATCHED_COUNT DESC, POST_TAG_COUNT - POST_TAGS_MATCHED_COUNT ASC;