如何在同一个表中的一个MySQL查询中获取两组结果


How can I fetch two sets of results in a single MySQL query from the same table?

我有一个MySQL注释表,如下所示:

+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| userid     | int(11)          | NO   |     | 0       |                |
| comment    | char(255)        | NO   |     | NULL    |                |
| content    | int(11)          | NO   | MUL | 0       |                |
| ratings    | int(11)          | NO   |     | 0       |                |
| datetime   | datetime         | NO   |     | NULL    |                |
| ip         | int(10) unsigned | NO   |     | NULL    |                |
| is_updated | tinyint(2)       | NO   |     | 0       |                |
| record_num | int(11)          | NO   | PRI | NULL    | auto_increment |
+------------+------------------+------+-----+---------+----------------+

现在,我可以使用这样的INNER JOIN查询从中获取注释,并从另一个表中获取用户名。

我可以得到顶部的三个评论ORDER BY comments.ratings DESC:

SELECT comments.userid, users.username, comments.comment, comments.ratings, comments.datetime, comments.record_num , content.uploader , content.anonymous
FROM comments
LEFT JOIN users ON  comments.userid = users.record_num
LEFT JOIN content ON comments.content = content.record_num
WHERE comments.content = ? ORDER BY comments.ratings DESC limit 3

获取定期评论ORDER BY comments.datetime DESC

SELECT comments.userid, users.username, comments.comment, comments.ratings, comments.datetime, comments.record_num , content.uploader , content.anonymous
FROM comments
LEFT JOIN users ON  comments.userid = users.record_num
LEFT JOIN content ON comments.content = content.record_num
WHERE comments.content = ? ORDER BY comments.datetime DESC limit ?, ?

我试着先按用户的评分向用户显示前三名的评论,然后按评论的顺序向用户显示常规评论。datetime DESC。

现在,我如何将以上两个MySQL查询合并为一个查询呢?

正如另一个答案所说,您可以使用union组合结果,这只意味着将两个结果连接在一起。然而,需要注意的是,你不能简单地将这两个查询直接union放在一起,因为它们使用order by,所以我们需要将它们封装在外部查询中,并使用排名变量来确保我们可以按照我们想要的顺序重建并集:

select * from (
    SELECT 1 as tbl, 
           comments.userid, 
           users.username, 
           comments.comment, 
           comments.ratings, 
           comments.datetime, 
           comments.record_num, 
           content.uploader, 
           content.anonymous,
           @rank := @rank + 1 as rank
    FROM comments 
      LEFT JOIN users ON  comments.userid = users.record_num 
      LEFT JOIN content ON comments.content = content.record_num
      CROSS JOIN (select @rank := 0 ) q
    WHERE comments.content = ? ORDER BY comments.ratings DESC limit 3
) q1    
UNION ALL
select * from (    
    SELECT 2 as tbl, 
           comments.userid, 
           users.username, 
           comments.comment, 
           comments.ratings, 
           comments.datetime, 
           comments.record_num, 
           content.uploader, 
           content.anonymous,
           @rank := @rank + 1 as rank
    FROM comments 
      LEFT JOIN users ON  comments.userid = users.record_num 
      LEFT JOIN content ON comments.content = content.record_num
      CROSS JOIN (select @rank := 0 ) q
    WHERE comments.content = ? ORDER BY comments.datetime DESC limit ?, ?
) q2
ORDER BY tbl asc, rank asc;

默认情况下,uniondistinct,这意味着它不会重复在两个结果集中找到的行,但也不能保证这些行会按照您期望的顺序返回,因此需要用自己的tbl值标记每个表,然后用order by标记该字段。

如果您确定不会有重复,您可以使用union all而不是union 来消除重复检查

要回答您的问题,是的,您可以使用UNION组合查询,

我试着先按评分向用户显示前三条评论,然后按评论顺序向用户显示常规评论。datetime DESC

如果您正试图实现类似Stack Overflow的注释功能,其中首先显示顶部注释(或具有支持票的注释),那么我认为单独的查询就足够了

如果您的查询是组合的,则用户需要加载所有顶部和常规注释。此外,在某种程度上很难用具有UNION的大查询来制作或实现分页(根据我的经验,因为我还不懂编码)。

免责声明:很难,但并非不可能

如果我要编写这个问题的代码,首先我的程序将加载前三个注释。之后,有一个"显示更多评论"按钮,它将使用Ajax发布到我的服务器,并将结果(常规评论)附加到显示的评论列表中。这样一来,查询就需要像现在这样分开。

要将结果集堆叠成一个集,需要使用"UNION"-https://dev.mysql.com/doc/refman/5.0/en/union.html