Hibernate HQL внутренний подвыбор - PullRequest
0 голосов
/ 19 февраля 2019

Я получил следующий SQL, который я хотел преобразовать в действительный HQL.Проблема в том, что не разрешено присоединяться к подзапросу согласно docs .Несмотря на то, что это старые документы (v3.3), этот раздел все еще сохраняется в hibernate 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

Я придумал этот 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

Попытка выполнитьэтот запрос HQL приводит к исключению

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

, которое намекает на ( в INNER JOIN (SELECT.

Есть ли способ присоединиться к подзапросам в HQL?Если нет, то как лучше всего достичь тех же результатов, что и в SQL с HQL?


Я не очень хорош в преобразовании inner join on <sub-query> в фактическое предложение whereгде разрешен подзапрос

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

С помощью ответа @ 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

Ранее я выполнял этот собственный SQL-запрос с ResultTransformer:

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

.На самом деле небольшие различия с результатами между двумя запросами, но они не согласованы.Под последовательным я подразумеваю в данном случае, что не для всех возможных date результаты отличаются, только для некоторых.Также для предоставленного параметра :name результаты согласуются.Я буду больше оценивать, какие результаты более подходящие, но я не удивлюсь, если новые будут правильными.

0 голосов
/ 21 февраля 2019

Я думаю, что ваш 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

Это должно быть проще для перевода на HQL, и это может быть даже более правильным, потому что ваш оригинальный запрос, кажется, создает нежелательный декартовыйproduct между самосоединяемыми строками.

Вероятно, есть еще лучший способ сделать запрос в SQL без самостоятельного присоединения к таблице Foo, используя один проход через таблицу.Но для этого мне нужно больше узнать о вашем реальном сценарии использования и о том, какую СУБД вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...