我有两个表,一对多的关系(测验,评论):一个测验可以有多个评论
我需要在页面内显示每个测验的最后5条评论。
是否可以使用一个查询提取这些评论(如果不是,这是最好的方法)?现在我正在为每个测验执行单独的查询以提取最后5条评论。
(我希望找到一个单独的HQL来允许我提取这些评论)
PS。我正在使用hibernate / jpa / mysql
答案 0 :(得分:2)
我写了一个用MySQL运行的复杂SQL ;-)
基本理念是:
前置条件是较新date
的评论有较高的id
更新:更改了SQL。 (在我的一小组测试数据中实现了一些缺少的测试用例)
这部分SQL后来使用了两次......你应该用它创建一个View。
SELECT
@rownum:=@rownum+1 AS Rank,
c.*
FROM _comments c, (SELECT @rownum:=0) r
ORDER BY c.q_id, c.id
-
SELECT
ranked_c.*
FROM (
SELECT
@rownum:=@rownum+1 AS Rank,
c.*
FROM _comments c, (SELECT @rownum:=0) r
ORDER BY c.q_id, c.id
) ranked_c
INNER JOIN (
SELECT
i.q_id,
MAX(i.Rank) AS LastEntry_id
FROM (
SELECT
@rownum:=@rownum+1 AS Rank,
c.*
FROM _comments c, (SELECT @rownum:=0) r
ORDER BY c.q_id, c.id
) i
GROUP BY i.q_id
) max_c ON ranked_c.q_id = max_c.q_id
WHERE max_c.LastEntry_id - ranked_c.Rank BETWEEN 0 AND 4
替代where子句:abs(max_c.LastEntry_id - ranked_c.Rank) < 5
<强> - &GT;使用视图的解决方案:
CREATE OR REPLACE VIEW V_RankedComments AS (
SELECT
@rownum:=@rownum+1 AS Rank,
c.*
FROM _comments c, (SELECT @rownum:=0) r
ORDER BY c.q_id, c.id
)
SELECT
ranked_c.*
FROM V_RankedComments ranked_c
INNER JOIN (
SELECT
i.q_id,
MAX(i.Rank) AS LastEntry_id
FROM V_RankedComments i
GROUP BY i.q_id
) max_c ON ranked_c.q_id = max_c.q_id
WHERE max_c.LastEntry_id - ranked_c.Rank BETWEEN 0 AND 4
答案 1 :(得分:0)
我认为你需要使用分析函数来做到这一点。这是一个example for Oracle。
在你的cas中,sql查询看起来像这样:
SELECT quizz_id, comment_id, comment_text FROM (
SELECT c.quizz_id, c.comment_id, c.comment_text, ROW_NUMBER()
OVER (PARTITION BY c.quizz_id ORDER BY c.date DESC) AS rn
FROM comments c)
WHERE rn <= 5 order by quizz_id, rn;
但是你无法使用HQL进行这种查询。
答案 2 :(得分:0)
我不认为这在hql中是可行的,但这是我尝试使用标准的sql:
SELECT
q.id AS quiz_id, c.id AS comment_id, c.text AS comment_text, c.date AS comment_date
FROM
quiz q
JOIN
comments c
ON
q.id = c.quiz_id
WHERE
c.id IN
(SELECT
id
FROM
comments c2
WHERE
c2.quiz_id = q.id
ORDER BY
date desc
LIMIT 5
)
ORDER BY
q.id ASC, c.date ASC
编辑:我认为这在hql中是不可能的原因是因为据我所知它不支持LIMIT,因为它不是标准的SQL。这也意味着我的示例不是100%纯标准SQL,但是mysql支持它 - 而且你使用mysql,所以我认为没关系。
EDIT2:修正了SQL,因为它错了。现在它使用了一个subselect(我不确定这是否很快,但我依赖于那里的查询优化器^^)。还在本地数据库上测试了它(postgres而不是mysql,但它应该在两者中都有效)。