LINUX.ORG.RU

SELECT по результатам другого SELECT?

 , ,


0

1

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

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

$sq = new SQLite3('../db.sq3');

$sq->exec('CREATE TABLE IF NOT EXISTS blog_posts (
post_id INTEGER PRIMARY KEY,  // ид поста (автоинкремент)
post_author INTEGER,          // ид пользователя
post_datetime INTEGER,        // дата создания
post_title TEXT,              // заголовок
post_contents TEXT,           // пост
post_intro TEXT               // превью поста
)');

$sq->exec('CREATE TABLE IF NOT EXISTS blog_comments (
comment_id INTEGER PRIMARY KEY,  // ид комментария (автоинкремент)
comment_author INTEGER,          // ид пользователя
comment_datetime INTEGER,        // дата создания
comment_contents TEXT            // комментарий
)');

$sq->exec('CREATE TABLE IF NOT EXISTS blog_entries (
post_id INTEGER,     // ид поста
comment_id INTEGER,  // ид комментария
entry_ip TEXT,       // айпи
entry_ua TEXT        // юзер агент
)');

посты лежат отдельно, комментарии отдельно, и таблица связующая комментарии с постами - тоже отдельно.

то есть, если мы хотим вывести все комментарии к посту, то сперва мы выберем id комментариев к нужному посту, а затем уже выберем все комментарии по этим id.

$stmt = $sq->prepare('SELECT comment_contents FROM blog_comments WHERE comment_id IN (SELECT comment_id FROM blog_entries WHERE post_id = :id)');
$stmt->bindValue(':id', $_GET['id'], SQLITE3_INTEGER);
$exec = $stmt->execute();

while ($row = $exec->fetchArray()) {
  print_r($row);
}

$sq->close();

похоже, что оно работает. для теста я записал 2 комментария в базу и на выхлопе получаю их самых.

Array ( [0] => note one [comment_contents] => note one )
Array ( [0] => note two [comment_contents] => note two )

все правильно сделал? и не нужно никаких join'ов (которые все ругают)?

★★★★★

Почему автор считает именно такой запрос наилучшим? Не будет ли он слишком медленным на больших таблицах?

Deleted ()
Ответ на: комментарий от Spoofing

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

Spoofing ★★★★★ ()
Ответ на: комментарий от Spoofing

а в чем особый смысл blog_entries? Непонятна цель. У тебя ведь основная операция на твоей базе будет простой select.

TheMixa ★★★ ()
Ответ на: комментарий от TheMixa

чтобы привязать комментарии к постам, в blog_entries

post_id | comment_id
1       | 1
1       | 2

и вот теперь из этой таблицы достаю список всех comment_id по post_id, а затем достаю уже комментарии из blog_comments по списку из comment_id :)

SELECT comment_contents FROM blog_comments WHERE comment_id IN (SELECT comment_id FROM blog_entries WHERE post_id = 1)

таким вот «вложенным» запросом.

собственно вопрос, это правильный подход или надо по другому делать?

Spoofing ★★★★★ ()
Ответ на: комментарий от Spoofing

Такая структура необходима, если комментарии и посты имеют отношение n к m. По логике жизни, каждый комментарий принадлежит не более чем одному посту, и можно было бы объединить blog_comments и blog_entries.

Но если и так всё работает, нет смысла переделывать.

Deleted ()
Ответ на: комментарий от Spoofing

А вот так не проще?
select id, content, ip, agent from comments where post_id = 1

Странный критерий «правильно».

TheMixa ★★★ ()
Ответ на: комментарий от Spoofing

собственно вопрос, это правильный подход или надо по другому делать?

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

TheMixa ★★★ ()

Не вижу причин почему нужна отдельная таблица на связи. Ведь комментарий всегда будет пренадлежать только доному посту

ZuBB ★★★★★ ()

Посоветуйте ОП хорошую книгу по проектированию структуры БД. По теме, blog_entries не нужно, join в общем случае ничем не хуже подзапроса.

goingUp ★★★★★ ()
Ответ на: комментарий от goingUp

Join лучше подзапроса. Он может быть оптимизирован.

ТопикСтертеру: таблица связей как было указанно лишняя.

1. Замержите comments и entries в таблицу comments.

2. создайте индекс по post_id в таблице

3. Смотрите ответ TheMixa

Обязательно прочитайте про join`ы. 99% задач для связанных таблиц решается с их помощью.

roller ★★★ ()
Ответ на: комментарий от Spoofing

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

ну ты и сделал ни как у всех, а именно через жоппу. Вот теперь и трахайся с вложенным селектами и/или join'ами. ССЗБ.

drBatty ★★ ()

comments ->
id | post_id | text | ...

SELECT text, ... FROM comments WHERE post_id = :id

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

marvin_yorke ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.