带max条件关联查询报错,如何获取各企业最新ContractType数据?
修正HQL查询以获取企业最新合同类型数据的方案
嗨,我来帮你解决这个查询报错的问题~你遇到的a column may not be outer-joined to a subquery错误,本质是HQL的语法限制:它不允许在LEFT JOIN的ON子句里嵌套子查询作为过滤条件。咱们换个思路,就能实现“获取每个企业对应其最新创建的合同类型”的需求。
方案一:HQL兼容写法(子查询预取最新时间)
我们可以先通过子查询找出每个福利周期(CompanyBenefitPeriods)下的最新合同创建时间,再通过“福利周期ID+最新时间”的组合来匹配对应的合同记录:
SELECT c.companyNo, cbp.companyBenefitNo, cct.companyContractNo, cct.createdOn FROM Company c LEFT JOIN c.companyBenefitPeriods cbp LEFT JOIN CompanyContractType cct ON cct.companyBenefitPeriod = cbp AND (cbp.companyBenefitPeriodNo, cct.createdOn) IN ( SELECT cbp_inner.companyBenefitPeriodNo, MAX(cct_inner.createdOn) FROM CompanyBenefitPeriods cbp_inner JOIN cbp_inner.companyContractType cct_inner GROUP BY cbp_inner.companyBenefitPeriodNo )
这个写法利用分组查询预获取每个福利周期的最新创建时间,再通过多列匹配的方式关联到对应的合同记录,避开了HQL的语法限制。
方案二:原生SQL窗口函数写法(高效简洁)
如果你的数据库支持窗口函数(比如MySQL 8+、PostgreSQL、SQL Server等),用ROW_NUMBER()窗口函数会更高效直观:
SELECT c.CompanyNo, cbp.CompanyBenefitNo, cct.CompanyContractNo, cct.CreatedOn FROM Company c LEFT JOIN CompanyBenefitPeriods cbp ON c.CompanyNo = cbp.CompanyNo LEFT JOIN ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY CompanyBenefitNo ORDER BY CreatedOn DESC ) AS rn FROM CompanyContractType ) cct ON cbp.CompanyBenefitNo = cct.CompanyBenefitNo AND cct.rn = 1 -- 如果你想排除没有合同记录的企业,可以加上下面的条件 -- WHERE cct.CompanyNo IS NOT NULL
这个逻辑是先给每个福利周期下的合同记录按创建时间倒序排号,取每个组里排号为1的(也就是最新的)记录,再和主表关联,完美匹配你的期望结果。
结果验证
用你提供的样本数据测试,两种方案都会返回:
| CompanyNo | CompanyBenefitNo | CompanyContractNo | CreatedOn |
|---|---|---|---|
| 1 | 1 | 2 | '27-11-2019' |
| 2 | 2 | 4 | '27-01-2020' |
内容的提问来源于stack exchange,提问作者Hiệp Tuấn




