Utilizzando un'istruzione CASE in HQL selezionare
-
19-08-2019 - |
Domanda
Esiste un modo per eseguire le seguenti operazioni in HQL:
SELECT
case when flag = true then SUM(col1) else SUM(col2)
FROM
myTable
Altri suggerimenti
Apparentemente la possibilità di farlo era aggiunto in 3.0.4 , con la limitazione che non è possibile utilizzare i sottoselezioni nella clausola else.
Vedi il forum di Hibernate: https://forum.hibernate.org/viewtopic.php ? t = 942197
Risposta del team (Gavin): case è supportato nella clausola where, ma non nella clausola select in HB3.
E visto in JIRA con lo stato "Non risolto".
Di seguito è possibile trovare una query funzionante (ibernazione su postgresql) che utilizza 2 istruzioni case per sostituire un valore booleano con la rappresentazione testuale corrispondente.
SELEZIONA CASO ps.open QUANDO vero ALLORA 'APERTO' altrimenti 'CHIUSO' FINE, CASO ps.full QUANDO è vero ALLORA 'PIENO' altro FINE 'GRATUITA', ps.availableCapacity DA ParkingState come ps
Usiamo ampiamente la query HQL ibernata e penso che finalmente ci sia un modo hacker di fare una cosa del genere:
Supponendo che inizialmente avevamo una query di
i2.element.id =: someId
Quindi ha deciso di espandere questo per essere qualcosa del genere:
((i.element.id =: someId e i2.element.id =: someId) o (i2.element.id =: someId))
Ma c'era un problema in cui desideravamo che cercasse questo solo in base a classType, quindi un'istruzione case:
(case when type(i)=Item then
((i.element.id = :someId and i2.element.id=:someId) or (i2.element.id = :someId))
else
i.element.id = :someId
end)
Sopra non funzionerà, puoi fare una versione facile di sopra facendo:
(case when type(i)=Item then
i2.element.id
else
i.element.id
end)=:elementId
Ma questo in realtà non fa ciò di cui abbiamo bisogno, vogliamo che faccia esattamente la query sopra, quindi sapendo che puoi assegnare una variabile alla fine di un'istruzione case là dove bit di HQL:
(
(
(case when
type(r)=Item then
i.element.id
else
i.element.id end) = :elementId
and
(case when
type(r)=Item then
i2.element.id
else
i.element.id end) = :elementId
)
or
(case when
type(r)=Item then
i2.element.id
else
i.element.id end) = :elementId
)
Sono riuscito a far funzionare ora la query in base all'istruzione case, certo che è molto più lungo ma in realtà fa lo stesso della prima istanza
Ho riscontrato lo stesso problema in HQL, quindi ho risolto la seguente query
select CONCAT(event.address1,', ', CASE WHEN event.address2 IS NULL THEN '' ELSE concat(event.address2,', ') END, event.city from EventDetail event where event.startDate>=:startDate and event.endDate<=:endDate;
Questo è un esempio che utilizza un confronto di stringhe nella condizione:
SELECT CASE f.type WHEN 'REMOVE'
THEN f.previousLocation
ELSE f.currentLocation
END
FROM FileOperation f