【问题标题】:HQL - Aggregate function MAX() in SubqueryHQL - 子查询中的聚合函数 MAX()
【发布时间】:2026-01-17 17:35:01
【问题描述】:

好的,这应该很简单,但是对于我的生活,我想不通。我确切地知道如何使用 SQL 执行此操作,但对 HQL 非常陌生。

这是交易。我有一个存储分配的表 - 将文档分配给用户。在不同时间,文档会重新分配给另一个用户,但所有分配都存储在分配表中以供审核。有道理?像这样的......

id   documentID   userID   dateAssigned
--   ----------   ------   ------------
6    32           87       3/4/2013
7    83           87       2/3/2013
8    32           56       5/6/2013
9    12           56       1/2/2013

我需要显示当前分配给给定用户的文档列表。在上面的示例中,用户 56 分配了两个文档(文档 32 和 12),而用户 87 有一个(文档 83),因为文档 32 随后被分配给了另一个用户。还和我在一起吗?

我想要做的是为给定用户返回任何已分配文档的任何记录(随后未重新分配)。所以,如果我查询用户 56,我会得到记录 #8 和 #9,如果我查询用户 87,我会得到记录 #7。这就是我想做的。

我可以通过以下内容轻松获取每个文档的最新作业列表:

SELECT a.id AS id, a.documentID AS documentID, a.userID AS userID, MAX(sa.dateAssigned) AS dateAssigned FROM DocumentAssignments a GROUP BY documentID

那会返回...

id   documentID   userID   dateAssigned
--   ----------   ------   ------------
7    83           87       2/3/2013
8    32           56       5/6/2013
9    12           56       1/2/2013

但是,当然,如果我只是在其中添加一个 WHERE 子句,我不会得到我真正想要的。例如,如果我使用:

SELECT a.id AS id, a.documentID AS documentID, a.userID AS userID, MAX(sa.dateAssigned) AS dateAssigned FROM DocumentAssignments a WHERE userID=87 GROUP BY documentID

...这将返回...

id   documentID   userID   dateAssigned
--   ----------   ------   ------------
6    32           87       3/4/2013
7    83           87       2/3/2013

...这不好,因为记录 #6 不是文档 32 的最新分配记录。

所以,我想做的是......

SELECT b.id AS id, b.documentID AS documentID, b.userID AS userID, b.dateAssigned AS dateAssigned FROM DocumentAssignments b WHERE id IN (SELECT a.id AS id, MAX(sa.dateAssigned) AS dateAssigned FROM DocumentAssignments a GROUP BY documentID) AND b.userID=87

这几乎是完美的,除了 IN 子句当然不起作用,因为它包含两列(id 和 MAX(dateAssigned))。

了解困境吗?我试图找出一种方法来使用聚合 MAX() 函数来限定分组函数,但它不会出现在结果记录集中。那将解决问题。一定有一个优雅的解决方案,但我没有找到它。

非常感谢任何帮助。

干杯,

-福斯维克

【问题讨论】:

    标签: hibernate subquery hql correlated-subquery wavemaker


    【解决方案1】:

    1) 您可以返回所有记录,例如在第一个 HQL 中,然后在 Java 中进行过滤。

    2) 其他方式,在同一个子查询中过滤 ID 和用户:

    SELECT b.id AS id, b.documentID AS documentID,
    b.userID AS userID, b.dateAssigned AS dateAssigned
    FROM DocumentAssignments b
    WHERE (b.id, b.userID) IN (SELECT a.id AS id, a.userID AS userID,
                               MAX(sa.dateAssigned) AS dateAssigned
                               FROM DocumentAssignments a
                               GROUP BY documentID)
    AND b.userID=87
    

    查看此示例: http://docs.jboss.org/hibernate/core/3.5/reference/en-US/html/queryhql.html#queryhql-tuple

    3)如果方法2不起作用,请尝试过滤您的查询,添加用户与分配的最新文档相同的条件,如下所示:

    SELECT b.id AS id, b.documentID AS documentID,
    b.userID AS userID, b.dateAssigned AS dateAssigned
    FROM DocumentAssignments b
    WHERE id IN (SELECT a.id AS id, MAX(sa.dateAssigned) AS dateAssigned
                 FROM DocumentAssignments a
                 GROUP BY documentID)
    AND b.userID=87
    AND b.userID IN (SELECT a.userID AS userID, MAX(sa.dateAssigned) AS dateAssigned
                 FROM DocumentAssignments a
                 GROUP BY documentID)
    

    【讨论】: