Использование лимита на левое соединение в MySQL - PullRequest
0 голосов
/ 02 июня 2011

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

Мне нужно получить только 5 комментариев на пост. Я переписал запрос, но получаю сообщение об ошибке «каждая производная таблица должна иметь свой псевдоним».

SELECT posts.id AS postId, posts.body, users.id AS userId, users.displayname, comments.id AS commentId, comments.text, commenters.id, commenters.displayname
FROM posts
JOIN users ON posts.owneruserid = users.id
LEFT JOIN comments ON posts.id = comments.postid
    JOIN users AS commenters ON comments.userId = commenters.id
ORDER BY posts.createdAt

Новый запрос:

SELECT posts.id AS postId, posts.body, users.id AS userId, users.displayname
FROM posts
JOIN users ON posts.owneruserid = users.id
LEFT JOIN (
    SELECT comments.id AS commentId, comments.text AS commentText, commenters.id AS commenterId, commenters.displayname AS commenterDisplayName
    FROM comments
    JOIN users AS commenters ON comments.userid = commenters.id
    LIMIT 0,5
        ) AS comments ON comments.postid = posts.id
ORDER BY posts.createdAt

ОБНОВЛЕНИЕ Запрос теперь работает, но он не дает желаемого результата. Я хочу вывести 10 постов, по 5 комментариев для каждого поста. Это предельное условие будет применяться только к комментариям к первому обнаруженному сообщению.

Ответы [ 4 ]

1 голос
/ 02 июня 2011

по ошибке


  1. Добавьте псевдоним после вашего подзапроса.
    Пример: SELECT * FROM foo JOIN (select * from bar) AS <alias_here>

  2. Убедитесь, что у вас есть поле в таблице posts и оно называется createdAt. Я не уверен, что MySQL чувствителен к регистру, но опубликованная вами ошибка говорит createdat (в нижнем регистре 'A')

  3. У вас есть два LEFT JOIN s, но только один ON оператор. Объединение не является чем-то без крючка, чтобы присоединиться к нему. Пример: * +1021 *

    SELECT *   
    FROM foo JOIN bar ON (foo.id=bar.id) 
    LEFT JOIN (select * from foobar) AS baz **ON foo.id=baz.id**
    
  4. Чтобы присоединиться к полю, поле должно присутствовать в таблице, участвующей в объединении. Таким образом, в приведенном выше примере, если вы сопоставите foo.id с baz.id, id необходимо вернуть в подзапрос (baz).

1 голос
/ 02 июня 2011

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

SELECT posts.id AS postId, posts.body, users.id AS userId, users.displayname
FROM posts
JOIN users ON posts.owneruserid = users.id
LEFT JOIN (
    SELECT comments.id AS commentId, comments.text AS commentText, commenters.id AS commenterId, commenters.displayname AS commenterDisplayName
    FROM comments
    JOIN users AS commenters ON comments.userid = commenters.id
    LIMIT 0,5
) as some_alias --This is what's triggering the error
ORDER BY posts.createdAt

Даже если вы не выбираете из подзапроса, а просто используете его в качестве фильтра, вы должны псевдоним его.

1 голос
/ 02 июня 2011

Из комментариев об изменениях и комментариях, вот запрос, который, я думаю, вы ищете ... Внутренний запрос будет получать сообщения и кто инициировал публикацию, комментарии и кто оставил комментарии.Этот внутренний запрос также предварительно отсортирован с НАИБОЛЕЕ ПОСЛЕДНИЕМИ КОММЕНТАРИИ к вершине на postID.Используя этот результат, я присоединяюсь к переменным sql (@variables), чтобы увеличить @varRow при каждом новом комментарии и сбросить его на 1 при каждом изменении идентификатора поста (отсюда и внутренние порядки PreQuery по идентификатору поста FIRST).).Наконец, с помощью предложения HAVING, чтобы количество комментариев @varRow <6 получалось на уровне MOST 5 каждого сообщения. </p>

Если вы хотите ограничить количество сообщений, которые вы пытаетесь получить, я бы применил предложение WHERE (например, дата / время (если доступно) в INNER, который генерирует «PreQuery».

select straight_join
      PreQuery.*,
      @varRow := if( @LastPost = PreQuery.PostID, @varRow +1, 1 ) CommentRow,
      @LastPost := PreQuery.PostID PostID2
   from
      ( select
              posts.id PostID,
              posts.body,
              posts.CreatedAt,
              u1.id UserID,
              u1.DisplayName NameOfPoster,
              c.id,
              c.userid CommentUserID,
              c.text CommentText,
              u2.DisplayName CommentUserName
           from
              posts
                 join users u1
                    on posts.ownerUserID = u1.id

                 LEFT JOIN comments c
                    on posts.id = c.PostID

                    join users u2
                       on c.userid = u2.id 
            where
                  posts.id = TheOneParentIDYouWant
               OR posts.parentid = TheOneParentIDYouWant
            order by
               posts.ID,
               c.id desc ) PreQuery,

      (select @varRow := 0, @LastPost = 0 ) SQLVars

   having
      CommentRow < 6   

   order by
      PreQuery.postid,
      CommentRow

--- РЕДАКТИРОВАТЬ --- за комментарий Я ДУМАЮ, что вы подразумеваете под "родительским сообщением", с которым связаны комментарии, потому что они имеют идентификатор сообщения напрямую.Поскольку самый внутренний запрос выполняет объединение всех элементов / таблиц по всем направлениям, все вместе отправляются в путешествие ...

Post -> User (to get posting user name )
Post -> Comment (on Common Post ID -- left joined)
        Comment -> User ( to get commenting user name)

После того, как ТО выполнено и отсортировано по общему идентификатору поста и большинствунедавний комментарий отсортирован по началу, затем я применяю @vars ко всем возвращаемым строкам.Предложение HAVING удалит любой комментарий, где его последовательность находится за 5 раз, которые вы искали.

1 голос
/ 02 июня 2011

Вам нужно дать вашей производной таблице псевдоним:

SELECT posts.id AS postId, posts.body, users.id AS userId, users.displayname
FROM posts
JOIN users ON posts.owneruserid = users.id
LEFT JOIN (
        SELECT comments.id AS commentId, comments.text AS commentText, commenters.id AS commenterId, commenters.displayname AS commenterDisplayName
        FROM comments
        JOIN users AS commenters ON comments.userid = commenters.id
        LIMIT 0,5
    ) AS derived_table_alias
ORDER BY posts.createdAt
...