Case when in jpa #query - postgresql

I hope I can explain myself enough.
I'm working with JPA #Query. I need to do a Case-When.
If the id is from a certain company, return all employees, otherwise return only employees from that company
In PostgreSQL is working the query
SELECT * FROM VIEW_EMPLOYEE v
WHERE (v.name LIKE '%%' OR v.lastname LIKE '%%' OR v.sso LIKE '%%')
AND (CASE WHEN (SELECT c.acronym FROM company c WHERE id = 1) <> 'TH' THEN v.company_id = 1 ELSE TRUE END)
But when I code it in JPA #Query
#Query("SELECT u FROM ViewEmployee u WHERE (u.name LIKE %?1% OR u.lastname LIKE %?1% OR u.sso LIKE %?1%) " +
"AND (CASE WHEN (SELECT c.acronym FROM Company c WHERE c.id = ?2) <> 'TH' THEN u.viewEmployeeId.companyId = ?2 ELSE TRUE END)")
fun findEmployee(search: String, companyId: Long, pageable: Pageable): Page<ViewEmployee>
Give me this error message
unexpected token: = near line 1, column 251 [SELECT u FROM com.solucioneskuali.models.ViewEmployee u WHERE (u.name LIKE ?1 OR u.lastname LIKE ?1 OR u.sso LIKE ?1) AND (CASE WHEN (SELECT c.acronym FROM com.solucioneskuali.models.Company c WHERE c.id = ?2) <> 'TH' THEN u.viewEmployeeId.companyId = ?2 ELSE TRUE END)]
Can someone help to find what I'm doing wrong?

Related

Refine data elements using having clause tsql

I'm trying to pull a dataset that returns records ONLY when there are two QUALIFERs present. I've tried left joins, populating data in temp tables then manipulating something, then numerous having clauses (resulting in subquery selects, and additional groups). I would appreciate any assistance on what I can do further.
Query:
Select E, CASE WHEN QUALIFER = '1' THEN 'NAME1' WHEN QUALIFER = '2' then 'NAME2' ELSE 'FINALNAME' END AS TYPE, count(rt.ID) 'Number '
from TABLE_ONE co (nolock)
join TABLE_TWO rt (nolock)
on co.ID = rt.ID
where co.E in (select * from #tempEmail)
AND convert(date,co.INSERTED_TIMESTAMP)between '1/1/2020' and '8/15/2020'
AND TRANS_STATUS = 'APPROVED'
group by E, QUALIFER
order by E, QUALIFER
Current resultset:
E TYPE Number
FAKEEMAIL1#Gmail NAME1 1
FAKEEMAIL1#Gmail NAME2 1
otheremailj#gmail.com Name1 21
Desired resultset:
E TYPE Number
FAKEEMAIL1#Gmail NAME1 1
FAKEEMAIL1#Gmail NAME2 1
Thank you.
Let's try the below query. I used a temp table to make things more simple for my mind.
if object_id('tempdb.dbo.#email') is not null drop table #email
create table #email
(
email varchar(50),
typeValue varchar(15),
Number int
)
insert into #email(email, typeValue, Number)
Select
E,
CASE WHEN QUALIFER = '1' THEN 'NAME1' WHEN QUALIFER = '2' then 'NAME2' ELSE 'FINALNAME' END AS TYPE,
count(rt.ID) 'Number '
from TABLE_ONE co (nolock)
join TABLE_TWO rt (nolock)
on co.ID = rt.ID
where co.E in (select * from #tempEmail)
AND convert(date,co.INSERTED_TIMESTAMP)between '1/1/2020' and '8/15/2020'
AND TRANS_STATUS = 'APPROVED'
group by E, QUALIFER
select a.email, a.typeValue
from #email a
inner join
(
select email, typeValue, rank() over (partition by email order by typeValue) as typeCount
from #email t
) as b
on b.email = a.email
and b.typeCount > 1

View query without sub selecting T-SQL

so I'm trying to build a view query but I keep failing using only joins so I ended up with this deformation.. Any tips on how I can write this query so I don't have to use 6 subselects?
The FeeSum and PaymentSum can be null, so ideally I do not want those in my result set and I also wouldn't like results where the FeeSum and the PaymentSum are equal.
Quick note: client is the table where the clients informations are stored (name, adress, etc..)
customer has a fk on client and is kind of a shell table for the client that store more information for the client,
payment is a list of all payments a customer did,
order is a list of all orders a customer did.
The goal is to get a list where we can track which customer has open fees to pay, based on the orders. It's a legacy project so don't ask why people can order before paying :)
SELECT
cu.Id as [CustomerId]
, CASE
WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName
END as [Name]
, cl.CustomerNumber
, (SELECT SUM(o.Fee) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [FeeSum]
, (SELECT SUM(p.Amount) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [PaymentSum]
, (SELECT MAX(o.OrderDate) FROM [publication].[Order] o WHERE o.[State] = 2 AND o.CustomerId = cu.Id) as [LastOrderDate]
, (SELECT MAX(p.PaymentDate) FROM [publication].[Payment] p WHERE p.CustomerId = cu.Id) as [LastPaymentDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Reminder' AND f.ClientId = cl.Id) as [LastReminderDate]
, (SELECT MAX(f.Created) FROM [client].[File] f WHERE f.TemplateName = 'Warning' AND f.ClientId = cl.Id) as [LastWarningDate]
FROM
[publication].[Customer] cu
JOIN
[client].[Client] cl
ON cl.Id = cu.ClientId
WHERE
cu.[Type] = 0
Thanks in advance and I hope I didn't do anything wrong.
Kind regards
You could rewrite the correlated subqueries to instead use joins:
SELECT
cu.Id AS [CustomerId],
CASE WHEN cl.IsPerson = 1
THEN cl.[AdditionalName] + ' ' + cl.[Name]
ELSE cl.AdditionalName END AS [Name],
cl.CustomerNumber,
o.FeeSum,
p.PaymentSum,
o.LastOrderDate,
p.LastPaymentDate,
f.LastReminderDate,
f.LastWarningDate
FROM [publication].[Customer] cu
INNER JOIN [client].[Client] cl
ON cl.Id = cu.ClientId
INNER JOIN
(
SELECT CustomerId, SUM(Fee) AS [FeeSum], MAX(OrderDate) AS [LastOrderDate]
FROM [publication].[Order]
WHERE o.[State] = 2
GROUP BY CustomerId
) o
ON o.CustomerId = cu.Id
INNER JOIN
(
SELECT CustomerId, SUM(Amount) AS [PaymentSum], MAX(PaymentDate) AS [LastPaymentDate]
FROM [publication].[Payment]
WHERE o.[State] = 2
GROUP BY CustomerId
) p
ON p.CustomerId = cu.Id
INNER JOIN
(
SELECT ClientId,
MAX(CASE WHEN TemplateName = 'Reminder' THEN Created END) AS [LastReminderDate],
MAX(CASE WHEN TemplateName = 'Warning' THEN Created END) AS [LastWarningDate]
FROM [client].[File]
GROUP BY ClientId
) f
ON f.ClientId = cl.Id
WHERE
cu.[Type] = 0;

LEFT OUTER JOIN Increasing SUM. How to Prevent This?

Simplified version of query below, but fundamental gist of it:
WITH ClientSpend AS
(
SELECT
c.ClientName
, CONVERT(INT, (ROUND(SUM(CASE WHEN e.Type = 1 THEN e.Dollars ELSE 0 END), 0))) AS 1_Dollars
, CONVERT(INT, (ROUND(SUM(CASE WHEN e.Type = 2 THEN e.Dollars ELSE 0 END), 0))) AS 2_Dollars
-- There's a bunch more of these for different 'Types'
FROM Expense e WITH(NOLOCK)
INNER JOIN Client c WITH(NOLOCK)
ON c.ClientID = e.ClientID
GROUP BY c.ClientName
)
SELECT
ClientName
, 1_Dollars
, 2_Dollars
FROM ClientSpend
GROUP BY ClientName
Type 2 has its own Expense table which breaks out into more granular detail that I need for a final CASE/SUM line in the CTE SELECT.
I tried testing the above query with a LEFT JOIN to this [ExpenseType2] table ON as many indexes as I can, and I noticed that the SUM on the 2_Dollars is higher when doing this. I'm assuming it's making multiple records even though I'm not selecting anything from the [ExpenseType2] table.
How do I prevent this?
Thanks,
Why not using a sub query? Or a simple select statement? Or you may need to assert more information with sample data.
SELECT first_name, 1_Dollars, 2_Dollars FROM
(
SELECT
c.ClientName
, CONVERT(INT, (ROUND(SUM(CASE WHEN e.Type = 1 THEN e.Dollars ELSE 0 END), 0))) AS 1_Dollars
, CONVERT(INT, (ROUND(SUM(CASE WHEN e.Type = 2 THEN e.Dollars ELSE 0 END), 0))) AS 2_Dollars
-- There's a bunch more of these for different 'Types'
FROM Expense e WITH(NOLOCK)
INNER JOIN Client c WITH(NOLOCK)
ON c.ClientID = e.ClientID
GROUP BY c.ClientName
) a

JPA query additional group by

How to write JPA query for below SQL ?
select * from opstatus o where o.OPERATIONTYPE=2 and o.RECEIVEDFLAG =2 and o.SENDTIME in (select max(o1.SENDTIME)from opstatus o1 where (o1.OPERATIONTYPE=2 and o1.RECEIVEDFLAG =2) group by o1.dn);
Trying to run the below query
result = em.createQuery("select o from DTO o where "
+ "o.operationType=:operationType"
+ " and o.receivedFlag = :receivedFlag"
+ " and o.startTime in (select max(o1.startTime)from DTO o1 where
o1.receivedFlag = :receivedFlag group by o1.Dn) order by o.startTime").
setParameter("operationType","2").
setParameter("receivedFlag", "2").getResultList();
However during runtime below query gets genereated which has additional 'group by T2.DN' for which we get ' org.apache.openjpa.persistence.PersistenceException: ORA-00979: not a GROUP BY expression'
SELECT t0.OPERATIONID, t0.CURRENTSTEP, t0.DETAILEDSTEPS,t0.DN, t0.OPERATIONTYPE, t0.RECEIVEDFLAG, t0.REQUESTID, t0.SENDTIME FROM OPSTATUS t0, OPSTATUS t2 WHERE (t0.OPERATIONTYPE = ? AND t0.RECEIVEDFLAG = ? AND t0.SENDTIME IN (SELECT MAX(t1.SENDTIME) FROM OPSTATUS t1 WHERE (t1.OPERATIONTYPE = ? AND t1.RECEIVEDFLAG = ?) GROUP BY t1.DN)) GROUP BY t2.DN [params=?, ?, ?, ?]
How to prevent additional 'group by' getting appended ? I tried adding 'order by o.sendtime' no use .
Did you means select the last entry in every Dn group. If two different Dn have the same startTime and only one of it is the last(max) your query will fail. Because the o1 in the sub query not linked to the outer o, the OpenJPA will generate FROM OPSTATUS t0, OPSTATUS t2
Maybe you can change your query.
"select o from DTO o where "
+ "o.operationType=:operationType"
+ " and o.receivedFlag = :receivedFlag"
+ " and not exists (select o1 from DTO o1 where
o1.receivedFlag = :receivedFlag and o1.Dn = o.Dn and o1.startTime > o.startTime) order by o.startTime"

Return a subset of rows with a complex order by in T-SQL

I have a stored proc select statement that lookes like that:
SELECT
p.ID AS ID,
p.Title AS Title,
p.Text AS Text,
p.CategoryID AS CategoryID,
p.PostDate AS PostDate,
p.Author AS Author,
p.AuthorID AS AuthorID,
p.IsApproved AS IsApproved,
p.Rating AS Rating,
p.RatesCount AS RatesCount,
t.Text AS CategoryNameTranslation,
p.IsEventPost AS IsEventPost,
p.EventStart AS EventStart,
p.EventEnd AS EventEnd,
p.EventRegionID AS EventRegionID,
p.EventAddress AS EventAddress
FROM
Posts AS p
INNER JOIN
Categories AS c
ON c.ID = p.CategoryID
INNER JOIN
Translations AS t
ON c.TranslationID = t.ID
WHERE
p.ID = CASE WHEN #ID != 0 THEN #ID ELSE p.ID END AND -- In case if ID given
p.IsApproved = CASE WHEN #Approved != -1 THEN #Approved ELSE p.IsApproved END AND -- In case of approved status given
t.Language = #LangID
ORDER BY
CASE #OrderDirection
WHEN 'Desc' THEN
CASE #OrderBy
WHEN 'PostDate' THEN p.PostDate
END
END
DESC,
CASE #OrderDirection
WHEN 'Asc' THEN
CASE #OrderBy
WHEN 'PostDate' THEN p.PostDate
END
END
ASC;
I need to return a limited number of rows, but the ROW_NUMBER function requires an ORDER BY expression that is pretty complex here and it will be modified multiple times. Can the expression be somehow referenced from the main select statement or i just have to copy everything into the function's parameter?
I don't understand why you regard putting the ORDER BY into ROW_NUMBER as any more complex than putting it at the end of the query?
;WITH cte AS
(
SELECT
p.ID AS ID,
p.Title AS Title,
p.Text AS Text,
p.CategoryID AS CategoryID,
p.PostDate AS PostDate,
p.Author AS Author,
p.AuthorID AS AuthorID,
p.IsApproved AS IsApproved,
p.Rating AS Rating,
p.RatesCount AS RatesCount,
t.Text AS CategoryNameTranslation,
p.IsEventPost AS IsEventPost,
p.EventStart AS EventStart,
p.EventEnd AS EventEnd,
p.EventRegionID AS EventRegionID,
p.EventAddress AS EventAddress,
ROW_NUMBER() OVER (
ORDER BY
CASE #OrderDirection
WHEN 'Desc' THEN
CASE #OrderBy
WHEN 'PostDate' THEN p.PostDate
END
END
DESC,
CASE #OrderDirection
WHEN 'Asc' THEN
CASE #OrderBy
WHEN 'PostDate' THEN p.PostDate
END
END
ASC
) AS RN
FROM
Posts AS p
INNER JOIN
Categories AS c
ON c.ID = p.CategoryID
INNER JOIN
Translations AS t
ON c.TranslationID = t.ID
WHERE
p.ID = CASE WHEN #ID != 0 THEN #ID ELSE p.ID END AND -- In case if ID given
p.IsApproved = CASE WHEN #Approved != -1 THEN #Approved ELSE p.IsApproved END AND -- In case of approved status given
t.Language = #LangID
)
SELECT *
FROM cte
WHERE RN BETWEEN 11 AND 20
ORDER BY RN;
SELECT TOP 10
....