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
() автор топика
Ответ на: комментарий от 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
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.