2016-08-28 5 views
0

У меня есть три стола: users, posts и comments.ВЫБЕРИТЕ сообщения и их комментарии

Как сделать SELECT первые три сообщения, каждый со своим комментарием и первым трем комментариями?

Пример: SQL Fiddle

Цель заключается в создании таблицы, как один ниже

  • Первая строка каждого POST_ID группировка на пост
  • comment_id является комментарием граф, что пост в
  • Следующие строки являются первыми тремя комментариями к этому сообщению

Ожидаемый результат:

-- post_id comment_id user_id body    created_at 
-- 1   4   1   Hello. I'm Jane. August, 28 2016 14:12:01 
-- 1   1   2   Nice post, Jane. August, 28 2016 14:12:01 
-- 1   2   1   Thank you, John. August, 28 2016 14:12:01 
-- 1   3   2   You're welcome. August, 28 2016 14:12:01 
-- 2   2   1   This is post 2. August, 28 2016 14:12:01 
-- 2   5   2   I like this.  August, 28 2016 14:12:01 
-- 2   6   1   Why, thank you. August, 28 2016 14:12:01 
-- 3   0   1   This is post 3. August, 28 2016 14:12:01 
+3

Вы имеете в виду первые три должности или первые три сообщения для каждого пользователя? И лучше разместить схему таблицы в сообщении здесь на SO, а также в ссылке ... –

+0

То есть, выход должен быть 9 строк? post1-comm1, post1-comm2, post1-comm3, post2-comm1, ... – Mike

+0

@CharlesBretana Я имел в виду первые три периода сообщений. Я действительно хочу получить первые три сообщения для указанного (не для каждого) пользователя. Но я оставил эту часть, потому что хотел упростить свой вопрос, и решил, что знаю, как изменить запрос на работу для сообщений определенного пользователя, а не всех сообщений. – ma11hew28

ответ

1

Понимание логика ожидаемого результата

У вас есть довольно сложные требования для вашего ожидаемого результата.Из того, что я понял из вашего SQL скрипку глядя на ожидаемый результат, вы хотите:

  1. получить первые три должности
  2. получить первые три комментарии для них
  3. добавить результат с 1 и 2 с различными логика для столбцов comment_id и body

разница в логике, кажется, как показано ниже:

Для каждой строки, представляющей поста:

  • в comment_id магазине количество комментариев на этот пост
  • в user_id магазине пользователь, который написал пост
  • в body магазине тело поста
  • в created_at хранить отметку времени, когда должность была создана

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

запросов и объяснение

Для живого примера взглянуть на SQL fiddle

Во-первых, взять первые три должности и построить строки для их подсчета комментариев для каждого из них. Затем объедините эти столбцы с строками комментариев и используйте функцию row_number(), чтобы ограничить строки комментариев в выводе до максимум 3 за сообщение.

Присвоение 0 в качестве номера строки для сообщений означает, что они выполняют условие rn <= 3.

Чтобы сделать вывод по вашему желанию, чтобы для каждого сообщения их комментарии отсортированы сразу после них, я добавил order_column, чтобы включить его в ORDER BY.

WITH first_posts AS (
    SELECT p.id AS post_id, COUNT(c.id) AS comment_id, p.user_id, p.body, p.created_at 
    FROM (SELECT * FROM posts ORDER BY id LIMIT 3) AS p 
    LEFT JOIN comments AS c 
    ON p.id = c.post_id 
    GROUP BY 1, 3, 4, 5 
) 
SELECT post_id, comment_id, user_id, body, created_at 
FROM (
    SELECT 1 AS type, post_id, comment_id, user_id, body, created_at, 0 AS r 
    FROM first_posts 
    UNION ALL 
    SELECT 2 AS type, p.post_id, c.id, c.user_id, c.body, c.created_at, 
     ROW_NUMBER() OVER (PARTITION BY p.post_id ORDER BY c.id) AS r 
    FROM first_posts AS p 
    INNER JOIN comments AS c 
    ON p.post_id = c.post_id 
    ORDER BY post_id, type, comment_id 
) AS f 
WHERE r <= 3; 
+0

Да, вы понимаете логику вывода, который я хочу. Хотя, я не уверен, что результат, который я хочу, на самом деле является хорошей идеей (слишком умной?) Или если есть лучший способ получить все нужные мне данные. – ma11hew28

+0

Это вполне допустимый результат, но будет выглядеть лучше, если вы укажете, какая строка содержит информацию о сообщении и какие комментарии. Это можно легко сделать, добавив еще один столбец так же, как я сделал с 'order_column'. Почему вы хотите, чтобы такой вывод был другим вопросом. Я не знаком с вашими потребностями и проектами. –

+0

OK. Спасибо. Гарантированы ли правильные комментарии, даже если кто-то вставляет комментарий в середине этого запроса, то есть, если есть условие гонки? – ma11hew28

1

Вы можете использовать подзапрос, чтобы ограничить выбор для первых 3 сообщений и row_number включать только первые 3 комментариев за сообщение:

SELECT * FROM (
    SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY c.post_id ORDER BY c.id) rn 
    FROM posts p 
    JOIN comments c ON c.post_id = p.id 
    WHERE p.id IN (SELECT id FROM posts ORDER BY id LIMIT 3) 
) t WHERE rn <= 3 

или если вы хотите первые 3 сообщения & комментарии для пользователя

SELECT * FROM (
    SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY c.post_id ORDER BY c.id) comments_rn, 
     ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.id) post_rn   
    FROM posts p 
    JOIN comments c ON c.post_id = p.id 
    JOIN users u ON u.id = p.user_id 
) t WHERE comments_rn <= 3 and post_rn <= 3 
0

отредактированных Синтаксис и имена столбцов:

Select id, name, p.*, c.* 
from users u 
    join posts p on p.User_Id = u.Id 
     and (Select count(*) From posts 
      where user_Id = u.Id 
       and created_at <= p.created_at) <= 3 
    join comments c on c.post_Id = p.Id 
     and (Select count(*) From comments 
      where post_Id = p.Id 
       and created_at <= c.created_at) <= 3 
+1

Это должно быть 'user_id' вместо' userId'. То же самое с 'postId'. Кроме того, таблица users не имеет столбца 'user_id' и т. Д. ... –

+2

Вот почему вы должны помещать таблицу таблиц в сообщение не только по ссылке ... И вы на самом деле жалуетесь, потому что вам нужно отредактировать sql a немного? –

+1

Не могли бы вы взглянуть на имя пользователя, задающего вопрос и мою? Браво! –

Смежные вопросы