以下查询选择所有帖子和每个帖子的所有者,属于每个帖子的所有评论以及每条评论的所有者。
我每篇文章只需检索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条评论。此限制条款仅适用于遇到的第一篇帖子的评论。
答案 0 :(得分:1)
您需要为派生表提供别名:
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
答案 1 :(得分:1)
由于您正在使用子查询(这是“派生表”的含义),因此它必须具有别名。因此,您需要做的就是:
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
即使您没有从子查询中进行选择,只是将其用作过滤器,也必须使用别名。
答案 2 :(得分:1)
从编辑和评论反馈,这里是我认为你正在寻找的查询...最内部的预先查询获取帖子,谁发起了帖子,评论和谁发表评论。此内部查询也预先排序,每个postID的最顶层注释最多。使用结果,我加入sql变量(@variables)以在每次新注释时增加@varRow,并在每次帖子ID更改时重置为1(因此内部PreQuery命令通过帖子ID FIRST )。最后,使用HAVING子句使注释的@varRow计数< 6将获得每个帖子的第5个。
如果要限制要检索的帖子,我会在生成“PreQuery”的INNER中应用WHERE子句(如可用的日期/时间)。
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
---编辑---每条评论 我认为你的意思是与评论相关联的“父帖”是因为他们直接拥有帖子ID。由于最里面的查询会全面地连接所有元素/表格,所以所有元素/表格都会随之而来...
Post -> User (to get posting user name )
Post -> Comment (on Common Post ID -- left joined)
Comment -> User ( to get commenting user name)
一旦完成全部操作并按照常用的帖子ID排序,并将最新的评论排序到顶部,然后我将@vars应用于所有返回的行。 HAVING子句将删除任何注释,其中的序列超出了您所寻找的5个。
答案 3 :(得分:1)
在子查询后添加别名。
示例:SELECT * FROM foo JOIN (select * from bar) AS <alias_here>
确保posts
表中有一个字段,并将其称为createdAt
。我不确定MySQL是否区分大小写,但您发布的错误显示createdat
(小写'A')
您有两个LEFT JOIN
,但只有一个ON
语句。连接不是没有钩子加入它的任何东西。例如:
SELECT *
FROM foo JOIN bar ON (foo.id=bar.id)
LEFT JOIN (select * from foobar) AS baz **ON foo.id=baz.id**
为了加入某个字段,该字段需要出现在连接所涉及的表中。因此,在上面的示例中,如果您将foo.id
与baz.id
匹配,则需要在子查询(baz)中返回id
。