Java 简单但复杂的HQL/SQL查询

Java 简单但复杂的HQL/SQL查询,java,mysql,sql,jpa,hql,Java,Mysql,Sql,Jpa,Hql,我有两个表格,一对多的关系测验,评论:一个测验可以有多个评论 我需要在页面内显示每个测验的最后5条评论 如果没有,哪种方法是最好的,是否可以使用一个查询提取这些评论?现在,我正在为每个测验执行一个单独的查询,以提取最后5条注释 我希望能找到一个单一的HQL来允许我提取这些评论 另外,我正在使用hibernate/jpa/mysql,我认为您需要使用分析函数来实现这一点。这是一个例子 在cas中,sql查询如下所示: SELECT quizz_id, comment_id, comment_tex

我有两个表格,一对多的关系测验,评论:一个测验可以有多个评论

我需要在页面内显示每个测验的最后5条评论

如果没有,哪种方法是最好的,是否可以使用一个查询提取这些评论?现在,我正在为每个测验执行一个单独的查询,以提取最后5条注释

我希望能找到一个单一的HQL来允许我提取这些评论


另外,我正在使用hibernate/jpa/mysql,我认为您需要使用分析函数来实现这一点。这是一个例子

在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进行此类查询。

我编写了一个复杂的SQL,它使用MySQL运行- 基本理念是:

对注释进行排序,并添加rownum作为排名。对同一个测验的评论已经产生了连续的数字排名 加入每个测验的最新评论的最大聚合 通过添加这些信息,可以构建where子句来限制每次测验的评论 前提条件是日期较新的注释具有较高的id

更新:已更改SQL。在我的一小部分测试数据中发现了一些缺失的测试用例 SQL的这一部分稍后将使用两次。。。您应该使用它创建一个视图

SELECT 
  @rownum:=@rownum+1 AS Rank,
  c.*
FROM _comments c, (SELECT @rownum:=0) r
ORDER BY  c.q_id, c.id
-

替代where子句:absmax_c.LastEntry_id-排名_c.Rank<5

->使用视图的解决方案:


我认为这在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中不可能的原因是,据我所知,它不支持限制,因为它不是标准SQL。这也意味着我的示例不是100%纯标准SQL,但mysql支持它——而且您使用mysql,所以我认为这没关系


EDIT2:修复了SQL,因为它是错误的。现在它使用了一个subselect,我不确定这是否很快,但我依赖那里的查询优化器^^。也在本地数据库postgres而不是mysql上测试了它,但它应该在这两种数据库中都能工作。

对于频繁的编辑表示抱歉。我最初的测试数据没有涵盖现实生活中的用例,我发现我的代码每出现一个新的用例都会中断。这会返回5条最新的注释,但不是每个quizyeah返回5条最新的注释,我在本地测试中也注意到了这一点。现在我修好了,好主意。但是MySQL有一个令人讨厌的限制:测试了MySQL 5.1和5.5[错误代码:1235,SQL状态:42000]这个版本的MySQL还不支持“LIMIT&IN/ALL/ANY/SOME subquery”嗯,好吧,这使得我的示例不起作用。好的,那么你的帖子bw_uezi是唯一一个适用于mysql的。如果我已经可以投票了,我会投票支持你的答案。检查:检查:在这里检查其他标有GREATEST-n-per-group的问题
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 
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