Hibernate generate sql query missing "(" character - spring

I faced an issue when I use #Query
#Query(value = "select c.id as id, c.store_id as store_id, c.name as name, c.type as type, c.rate as rate, " +
"(select count(pc.partner_id) from partner_commission pc where pc.commission_id = c.id) as number_of_partner " +
"from commission c join partner_commission pc on c.id = pc.commission_id where c.store_id=:storeId", nativeQuery = true)
Page<Commission> findCommissionForManagement(#Param("storeId") Long storeId, Pageable pageable);
I already tested this script on database (postgresql), it worked! But, the sql script generated by hibernate as below:
Hibernate: select c.id as id, c.store_id as store_id, c.name as name, c.type as type, c.rate as rate, (select count(pc.partner_id) from partner_commission pc where pc.commission_id = c.id) as number_of_partner from commission c join partner_commission pc on c.id = pc.commission_id where c.store_id=? limit ?
Hibernate: select count(pc) from partner_commission pc where pc.commission_id = c.id) as number_of_partner from commission c join partner_commission pc on c.id = pc.commission_id where c.store_id=?
2021-08-16 04:05:44.645 WARN 15976 --- [llCommissions-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 42601
2021-08-16 04:05:44.645 ERROR 15976 --- [llCommissions-1] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: syntax error at or near ")"
Position: 74
I hope to get some help

It seems like #Query has broken up the subquery incorrectly. Can you restructure the query using Joins?
Here is my suggestions, not tested but I hope you can debug it further to get your desired result.
SELECT
c.id AS id,
c.store_id AS store_id,
c.name AS name,
c.type AS type,
c.rate AS rate
pc.count AS number_of_partner
FROM
commission c
LEFT JOIN (
SELECT
id,
COUNT(*) AS count
FROM
partner_commission
GROUP BY
partner_commission.id
) AS pc
ON pc.id = c.store_id
WHERE
c.store_id = :storeId

Seems like a Spring Data JPA bug. You can try to workaround this by providing a custom count query in the #Query annotation.

Related

PL-SQL how to inner join twice on the same table

I'm trying to make a query that joins a table twice for language purpose.
But SQL Developer always throws an error
Invalid Identifier in the SELECT
when I try to use the ALIAS of my table (table2 is invalid)
SELECT
table1.code Code,
table2.descr DescrFr,
table3.descr_en DescrEn
FROM
main_table table1
INNER JOIN
descr_table table2 ON table1.code = table2.code
AND table2.lang = 'fr'
INNER JOIN
descr_table table3 ON table1.code = table3.code
AND table3.lang = 'en'
I didn't find anything helpful for my case that could teach me what's wrong with my query.
EDIT
Tested asked by user but resulted with this error
Erreur SQL : ORA-00904: "TABLE3"."code" : identificateur non valide
SELECT
table1.code AS Code,
table2.descr AS DescrFr,
table3.descr AS DescrEn
FROM main_table table1
INNER JOIN descr_table table2 ON (table1.code = table2.code)
INNER JOIN descr_table table3 ON (table1.code = table3.code)
WHERE (table2.lang = 'fr' AND table3.lang = 'en');
Answer
The result is a facepalm... the initial query is working.. i was just using the wrong column name in the descr_table...
I don't know the version you are using but I guess you could try SELECT table1.code AS Code,.... And I would prefer not using so much INNER JOIN in your sql query rather would use at least one RIGHT JOIN or LEFT JOIN because you need to have a "main table" which has the highest priority.
AND of course there is something wrong I guess.
so your code would be fine in this way:
SELECT
table1.code AS Code,
table2.descr AS DescrFr,
table3.descr_en AS DescrEn
FROM
main_table AS table1
INNER JOIN
descr_table AS table2 ON (table1.code = table2.code)
INNER JOIN
descr_table table3 ON (table1.code = table3.code)
WHERE
(table2.lang = 'fr' AND table3.lang = 'en')
I'd avoid the double join altogether.
and never use aliases such as table1
This could be...
SELECT
main.Code,
descr.DescrFr,
descr.DescrEn
FROM
main_table main
INNER JOIN
(
SELECT
code,
MAX(CASE WHEN lang = 'fr' THEN descr END) AS DescrFr,
MAX(CASE WHEN lang = 'en' THEN descr END) AS DescrEn
FROM
descr_table
WHERE
lang IN ('fr', 'en')
GROUP BY
code
)
descr
ON descr.code = main.code
(And even then, from your description, you don't even need the outer join as the code exists in the descr_table.)

How can I solve the ORA-01799 when creating a VIEW with a LEFT OUTER JOIN and a MAX value?

I am trying to create a view that joins a few tables, one of the joins is using a max value and I think that is generating the following error in our Oracle DB:
ORA-01799: a column may not be outer-joined to a subquery.
Can anyone help me to change the estatement to create the view? The query works fine, the problem only comes when I try to create a view with it.
CREATE or replace VIEW xxxxxx_V (ID, SERVICE_ID, PARENT_ID, PARENT_MATERIALITY, PARENT_END_STATUS,
PARENT_OUTS_TYPE, END_STATUS, MATERIALITY, OUTS_TYPE, CREATED_BY,
SERVICE_DESCRIPTION_SHORT, VERSION, OUTSOURCER_ID, OUTSOURCER_NAME, INSOURCER_ID, INSOURCER_NAME, PLANNED_SERVICE_START) AS
select c.id id, s.id service_id, s.outsourcing_id parent_id, p.materiality parent_materiality, p.end_status parent_end_status,
p.outsourcing_type parent_outs_type, c.end_status end_status, c.materiality materiality, c.outsourcing_type outs_type, c.created_by created_by,
r.service_description_short, r.version, r.outsourcer outsourcer_id, o.name outsourcer_name , r.insourcer insourcer_id,i.name insourcer_name, r.planned_service_start
from OS_OUTSOURCING_CONTRACT c
left join OS_SERVICES s on s.id = c.service_id
left join OS_OUTSOURCING_CONTRACT p on p.id = s.outsourcing_id
left join OS_RISK_ASSESSMENT r on r.outsourcing_id = c.id and r.version = (select max(version) from OS_RISK_ASSESSMENT where outsourcing_id = c.id)
left join OS_COMPANY_INSOURCER i on i.id = r.insourcer
left join OS_COMPANY_OUTSOURCER o on o.id = r.outsourcer
Join the subquery into the query:
CREATE or replace VIEW xxxxxx_V
(ID, SERVICE_ID, PARENT_ID, PARENT_MATERIALITY, PARENT_END_STATUS,
PARENT_OUTS_TYPE, END_STATUS, MATERIALITY, OUTS_TYPE, CREATED_BY,
SERVICE_DESCRIPTION_SHORT, VERSION, OUTSOURCER_ID, OUTSOURCER_NAME,
INSOURCER_ID, INSOURCER_NAME, PLANNED_SERVICE_START) AS
select c.id,
s.id service_id,
s.outsourcing_id parent_id,
p.materiality parent_materiality,
p.end_status parent_end_status,
p.outsourcing_type parent_outs_type,
c.end_status,
c.materiality,
c.outsourcing_type outs_type,
c.created_by,
r.service_description_short,
r.version,
r.outsourcer outsourcer_id,
o.name outsourcer_name,
r.insourcer insourcer_id,
i.name insourcer_name,
r.planned_service_start
from OS_OUTSOURCING_CONTRACT c
LEFT OUTER JOIN (select outsourcing_id,
max(version) AS MAX_VERSION
from OS_RISK_ASSESSMENT
group by outsourcing_id) ora
ON ora.OUTSOURCING_ID = c.id
left join OS_SERVICES s
on s.id = c.service_id
left join OS_OUTSOURCING_CONTRACT p
on p.id = s.outsourcing_id
left join OS_RISK_ASSESSMENT r
on r.outsourcing_id = ora.OUTSOURCING_ID and
r.version = ora.MAX_VERSION
left join OS_COMPANY_INSOURCER i
on i.id = r.insourcer
left join OS_COMPANY_OUTSOURCER o
on o.id = r.outsourcer

Invalid identifier when using left outer join in Oracle

I wrote a query with Left outer join in oracle.But I execute the query I get ORA-00904: "b"."GROSS_DISCOUNT_AMOUNT": invalid identifier error.TableB contains net_discount_number and gross_discount_amount columns.
select
a.GSMNO GSMNO,
a.NET_AMOUNT net,
a.GROSS_AMOUNT gross,
sum(b.net_discount_amount) net_discount, sum(b.gross_discount_amount) gross_discount,
a.code code, a.seq_no
from tableA a
LEFT OUTER JOIN
(select id, code, seq_no, sum(gross_amount) gross_amount, sum(net_discount_amount), sum(gross_discount_amount) from tableB
group by id, code, seq_no)
b ON a.id = b.id and NVL(a.code,b.code) = NVL(b.code,-99) and
NVL(a._seq_no,-99) = NVL(b.seq_no,-99)
and a.gross_amount = b.gross_amount
where a.tvNo like '123% and gsmno ='1111111111'
group by
a.GSMNO,
a.NET_AMOUNT,
a.GROSS_AMOUNT,
a.code, a.seq_no
You haven't specified aliases for aggregate sums, it should be like this:
select
a.GSMNO GSMNO,
a.NET_AMOUNT net,
a.GROSS_AMOUNT gross,
sum(b.net_discount_amount) net_discount, sum(b.gross_discount_amount) gross_discount,
a.code code, a.seq_no
from tableA a
LEFT OUTER JOIN
(select id, code, seq_no,
sum(gross_amount) gross_amount,
sum(net_discount_amount) net_discount_amount,
sum(gross_discount_amount) gross_discount_amount
from tableB
group by id, code, seq_no)
b ON a.id = b.id and NVL(a.code,b.code) = NVL(b.code,-99) and
NVL(a._seq_no,-99) = NVL(b.seq_no,-99)
and a.gross_amount = b.gross_amount
where a.tvNo like '123% and gsmno ='1111111111'
group by
a.GSMNO,
a.NET_AMOUNT,
a.GROSS_AMOUNT,
a.code, a.seq_no

ORA-00979: not a GROUP BY expression while querying a View with a subquery

I have a view as follows - It compiles just fine but when I try to select from it, I get a ORA-00979: not a GROUP BY expression error. If I eliminate the subquery (column 4) from the view, all works fine. Any ideas would be greatly appreciated! Thanks!!
select
l.LAB_GROUP,
l.NAME as LAB,
b.NAME as BENCH,
(select count(distinct s2.SAMPLE_NUMBER)
from SAMPLE s2 inner join TEST t2 on s2.SAMPLE_NUMBER = t2.SAMPLE_NUMBER and t2.STATUS in ('C', 'R') and s2.TEMPLATE <> 'QC_SAMPLE'
inner join LABORATORY_ENTRY le2 on t2.ANALYSIS = le2.ANALYSIS
where s2.LAB_GROUP = l.LAB_GROUP and le2.NAME = l.NAME and t2.X_BENCH = b.NAME and
((select count(t1.TEST_NUMBER)
from TEST t1
where t1.SAMPLE_NUMBER = t2.SAMPLE_NUMBER and t1.ANALYSIS = t2.ANALYSIS and t1.STATUS <> 'R') = 0)) as RFR
from LABORATORY l
inner join LABORATORY_ENTRY le on le.NAME = l.NAME
inner join X_BENCH b on b.NAME = le.X_BENCH
left join (SAMPLE s inner join TEST t on s.SAMPLE_NUMBER = t.SAMPLE_NUMBER and s.STATUS <> 'U'
and s.TEMPLATE <> 'QC_SAMPLE' and t.STATUS in ('I', 'P')) on t.ANALYSIS = le.ANALYSIS and s.LAB_GROUP = l.LAB_GROUP
left join V_LOC_DEPT_FAC ldf on ldf.LOCATION_NUMBER = s.STORAGE_LOC_NO
group by l.LAB_GROUP, l.NAME, b.NAME
If you need to use the group by (which will be the case if you add aggregating functions, but not as the query is currently written) you need to include the subquery in the group by as well. You can add this easiest by adding a SELECT outside your main query and appyling the GROUP BY at that level:
select lab_group, lab, bench, rfr
from
(
select
l.LAB_GROUP as lab_group,
l.NAME as LAB,
b.NAME as BENCH,
(select .....) as RFR
from LABORATORY l
inner join LABORATORY_ENTRY le on le.NAME = l.NAME
inner join X_BENCH b on b.NAME = le.X_BENCH
left join (SAMPLE s inner join TEST t on ...) on
t.ANALYSIS = le.ANALYSIS and
s.LAB_GROUP = l.LAB_GROUP
left join V_LOC_DEPT_FAC ldf on ldf.LOCATION_NUMBER = s.STORAGE_LOC_NO
) x
group by lab_group, lab, bench, rfr
Try removing the...
group by l.LAB_GROUP, l.NAME, b.NAME
As I don't think this is neccesary if you're doing the count within the subquery.
However, for performance reasons I would suggest rewriting your query so that you move the subquery into the FROM section rather than the SELECT one.

Convert SQL select statement to Linq

How can I convert the following SQL select statement to Linq?
SELECT u.Name FROM User u AS DDC
INNER JOIN Country c ON c.UserId = u.UserId
INNER JOIN (
SELECT AddressId,
Address,
PC,
FROM AddressTbl a
WHERE a.CountryId = 1
) AS Addresses ON Addresses.AddressId= u.AddressId
WHERE
u.UserIs = #UserId AND
Addresses.AddressId= #AddressId
Any good reading references?
from u in Users join
c in Country on c.UserId equals u.UserId
join a in Address on a.AddressId equals u.AddressId
where a.CountryId == 1
select u.Name
You can try this out
http://www.sqltolinq.com/

Resources