简体   繁体   English

Hibernate HQL内部联接子选择

[英]Hibernate HQL inner join subselect

I got the following SQL which I wanted to transform into valid HQL. 我得到了以下要转换为有效HQL的SQL。 The issue with this is, that its not permitted to join on a sub-query per the docs . 问题是,每个docs都不允许其加入子查询。 Even though these are old docs (v3.3) this section still seems to still hold in hibernate 5.3. 即使这些是旧版文档(v3.3),本节仍然在休眠5.3中仍然有效。

SELECT f.date,
    f.name,
    SUM(f.seats) 
FROM Foo f 
        INNER JOIN (SELECT fl.date,
                        fl.start + fl.end AS code 
                    FROM Foo fl 
                    WHERE fl.date >= (SELECT MAX(earliestDate) 
                                            FROM Bar) 
                        AND fl.name = :name) fl 
        ON f.start + f.end = code 
        AND f.date = fl.date 
WHERE f.date >= (   SELECT MAX(earliestDate) 
                        FROM Bar)   
GROUP BY f.date,
    f.name 
ORDER BY f.date ASC,
    SUM(f.seats) DESC

I came up with this HQL: 我想出了这个HQL:

SELECT NEW com.company.project.model.FooRepresentation( f.fooId.date,
    f.fooId.name,
    SUM(f.seats)) 
FROM Foo f 
        INNER JOIN (SELECT fl.fooId.date,
                        fl.fooId.start + fl.fooId.end AS code 
                    FROM Foo fl 
                    WHERE fl.fooId.date >= (SELECT MAX(earliestDate) 
                                            FROM FooConfig) 
                        AND fl.fooId.name = :name) fl 
        ON f.fooId.start + f.fooId.end = code 
        AND f.fooId.date = fl.fooId.date 
WHERE f.fooId.date >= ( SELECT MAX(earliestDate) 
                        FROM FooConfig) 
GROUP BY f.fooId.date,
    f.fooId.name 
ORDER BY f.fooId.date ASC,
    SUM(f.seats) DESC

Trying to execute this HQL query, results in this exception 尝试执行此HQL查询会导致此异常

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 169

which hints to the ( at INNER JOIN (SELECT . 提示(INNER JOIN (SELECT

Is there a way to join on sub-queries within HQL? 是否可以在HQL中加入子查询? If not, what would be the best way to achieve the same results as the SQL with HQL? 如果不是,与HQL的SQL取得相同结果的最佳方法是什么?


I am not that good with converting the inner join on <sub-query> to an actual where clause where the sub-query is permitted 我不能将inner join on <sub-query>inner join on <sub-query>转换为允许子查询的实际where子句

I think your SQL query can be rewritten to this: 我认为您的SQL查询可以改写为:

SELECT f.date, f.name, SUM(f.seats) 
FROM Foo f 
WHERE EXISTS (
  SELECT 1
  FROM Foo f1
  WHERE f.start + f.end = f1.start + f1.end
  AND f.date = f1.date
  AND f1.date >= (SELECT MAX(earliestDate) FROM Bar)
  AND f1.name = :name  
)
AND f.date >= (SELECT MAX(earliestDate) FROM Bar)
GROUP BY f.date, f.name
ORDER BY f.date ASC, SUM(f.seats) DESC

This should be simpler to translate to HQL, and it might even be more correct, because your original query seems to create an unwanted cartesian product between the self joined rows. 转换为HQL应该更简单,甚至可能更正确,因为您的原始查询似乎在自连接行之间创建了不需要的笛卡尔积。

There's probably an even better way to query this in SQL, without self joining the Foo table, using a single pass through the table. 可能有一种更好的方法来查询SQL,而无需通过单次遍历表就自动加入Foo表。 But I'd need to know more about your real world use-case for that, and what RDBMS you're using. 但是我需要更多地了解您的实际用例,以及正在使用的RDBMS。

With the help of @LukasEder's answer, I created this HQL: 借助@LukasEder的答案,我创建了以下HQL:

SELECT NEW com.company.project.model.FooRepresentation( f.fooId.date,
    f.fooId.name,
    SUM(f.seats) ) 
FROM Foo f 
WHERE EXISTS (  SELECT 1 
                FROM Foo f1 
                WHERE f.fooId.start + f.fooId.end = f1.fooId.start + f1.fooId.end 
                    AND f.fooId.date = f1.fooId.date 
                    AND f1.fooId.date >= (  SELECT MAX(earliestDate) 
                                            FROM FooConfig) 
                    AND f1.fooId.name = :name ) 
    AND f.fooId.date >= (   SELECT MAX(earliestDate) 
                            FROM FooConfig) 
GROUP BY f.fooId.date,
    f.fooId.name 
ORDER BY f.fooId.date ASC,
    SUM(f.seats) DESC

Previously I was running this native SQL query with a ResultTransformer : 以前,我使用ResultTransformer运行此本机SQL查询:

SELECT f.date,
    f.name,
    SUM(f.seats) 
FROM Foo f 
        INNER JOIN (SELECT fl.date,
                        fl.start + fl.end AS code 
                    FROM Foo fl 
                    WHERE fl.date >= (  SELECT MAX(earliestDate) 
                                        FROM FooConfig) 
                        AND fl.name = :name) fl 
        ON f.start + f.end = code 
        AND f.date = fl.date 
WHERE f.date >= (   SELECT MAX(earliestDate) 
                    FROM FooConfig) 
GROUP BY f.date,
    f.name 
ORDER BY f.date ASC,
    SUM(f.seats) DESC

there are actually slight differences with the results between the two queries, but those are not consistent. 实际上,两个查询的结果之间存在细微的差异,但是并不一致。 With consistent I mean in this case, that its not for every possible date that the results differ, just for some. 在此情况下,我的意思是一致的,并不是在每个可能的date结果都不同,而只是在某些方面。 Also for the provided parameter :name , the results are consistent. 同样对于提供的参数:name ,结果也是一致的。 I will evaluate more on which results are more fitting, but I wouldn't be surprised if the new ones are correct. 我将对哪些结果更合适进行更多的评估,但是如果新结果正确,我不会感到惊讶。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM