I've been trying to write a working postgres query in JPA, but I'm getting errors in Intellij and when I run Spring it fails with a generic validation exception.
This is my query in postgres
SELECT
( "header" :: json ) ->> 'company' AS "Company",
LOWER(( "header" :: json ) ->> 'user') AS "User",
MAX ( ( "header" :: json ) ->> 'version' ) AS "Version",
MIN ( date_res ) AS "First CN",
MAX ( date_res ) AS "Last CN",
SUM ( CASE WHEN url = '/url-1' AND status = 200 THEN 1 ELSE 0 END ) AS "Survey",
SUM ( CASE WHEN url = '/url-2' AND status = 200 THEN 1 ELSE 0 END ) AS "Work",
SUM ( CASE WHEN url = '/url-3' AND status = 200 THEN 1 ELSE 0 END ) AS "Home",
SUM ( CASE WHEN url = '/url-4' AND status = 200 THEN 1 ELSE 0 END ) AS "DeploySurvey",
SUM ( CASE WHEN url = '/url-5' AND status = 200 THEN 1 ELSE 0 END ) AS "DeployWork"
FROM
"public"."seg_ws_log_res"
INNER JOIN "seg_company" ON ("seg_company"."companyName" = ( "header" :: json ) ->> 'company')
WHERE
"service" = 'service'
AND NOT ( "header" :: json ) ->> 'company' IS NULL
AND NOT ( "header" :: json ) ->> 'user' IS NULL
AND NOT ( "header" :: json ) ->> 'company' = ''
AND NOT UPPER(( "header" :: json ) ->> 'user') IN ('USER_1', 'USER_2')
AND NOT ( "header" :: json ) ->> 'version' = 'Dev'
AND NOT UPPER(( "header" :: json ) ->> 'company') IN ('text_1','text_2','text_3')
GROUP BY
"Company",
"User"
ORDER BY
"Company",
"User";
This is my #Query code
#Query(value = "SELECT " +
"cast(log.header as json) ->> 'company' AS \"Company\"," +
"LOWER(cast(log.header as json) ->> 'user') AS \"User\"," +
"MAX ( cast(log.header as json) ->> 'version' ) AS \"Version\"," +
"MIN (log.dateRes) AS \"First CN\"," +
"MAX ( log.dateRes ) AS \"Last CN\"," +
"SUM ( CASE WHEN log.url = '/url-1' AND log.status = 200 THEN 1 ELSE 0 END ) AS \"Survey\"," +
"SUM ( CASE WHEN log.url = '/url-2' AND log.status = 200 THEN 1 ELSE 0 END ) AS \"Work\"," +
"SUM ( CASE WHEN log.url = '/url-3' AND log.status = 200 THEN 1 ELSE 0 END ) AS \"Home\"," +
"SUM ( CASE WHEN log.url = '/url-4' AND log.status = 200 THEN 1 ELSE 0 END ) AS \"DeploySurvey\"," +
"SUM ( CASE WHEN log.url = '/url-5' AND log.status = 200 THEN 1 ELSE 0 END ) AS \"DeployWork\"" +
"FROM" +
" SegWsLogResEntity log" +
"INNER JOIN SegCompanyEntity c ON (c.companyName = ( cast(log.header as json)) ->> 'company') " +
"WHERE" +
" log.service = 'service' " +
" AND NOT cast(log.header as json) ->> 'company' IS NULL " +
" AND NOT cast(log.header as json) ->> 'user' IS NULL " +
" AND NOT cast(log.header as json) ->> 'company' = '' " +
" AND NOT UPPER(cast(log.header as json) ->> 'user') IN ('USER_1', 'USER_2') " +
" AND NOT cast(log.header as json) ->> 'version' = 'Dev'" +
" AND NOT UPPER(cast(log.header as json) ->> 'company') IN ('text_1','text_2','text_3')" +
"GROUP BY" +
"\"Company\"," +
"\"User\"" +
"ORDER BY" +
"\"Company\"," +
"\"User\"")
In this line:
cast(log.header ->> 'company' as json) AS \"Company\"
in the operator --> the IDE indicates:
<expression> expected, got '>'
LOWER(cast(log.header as json) ->> 'user') AS \"User\"
In this line:
"MIN (log.dateRes) AS \"First CN\","
The IDE indicates:
identifier expected, got '"First CN"'
the same for the each identifier until the from
And in this line
"INNER JOIN SegCompanyEntity c ON (c.companyName = ( \"header\" :: json ) ->> 'company') " +
After the ON the IDE indicates
'(', , FUNCTION or identifier expected, got '('
I have gone through many posts about JPA and native queries but none seem to be similar to my problem.
The query you define in the jpa-#Query annotations is by default a JPQL query. JPQL doesn't understand Postgres (or any other DB) specific features e.g. Postgres' Json(b) type.
There is a flag nativeQuery in the #Query annotation. You can set this to true -- then your query won't be interpreted as JPQL but as native SQL. Obviously, this way, the query will only work with postgres.
#Query(
nativeQuery = true,
value = "SELECT..."
)
Related
I'am trying to translate this spring data JDBC query to spring spring data JPQL
"SELECT t.id FROM foo t WHERE t.id IN (" +
"SELECT l.foo_id FROM bar l " +
"JOIN (VALUES :keyValueCombinations ) AS i (input_name) ON l.name = i.input_name)" +
"GROUP BY l.foo_id " +
"HAVING COUNT(*) = :keyValueCombinationsSize" +
")"
Output for SQL Server is:
SELECT t.id FROM foo t WHERE t.id IN(SELECT l.foo_id FROM label l
JOIN (values ('test'), ('test1') ) AS i (input_name)
ON l.name = i.input_name GROUP BY l.foo_id
HAVING COUNT(*) = 2 )
Query for JQPL
"SELECT t FROM foo t WHERE t.id IN (" +
"SELECT l.foo.id FROM bar l " +
"JOIN (VALUES :keyValueCombinations ) AS i (input_name) ON l.name = i.input_name)" +
"GROUP BY l.foo.id " +
"HAVING COUNT(l) = :keyValueCombinationsSize" +
")"
Error on runtime is:
[27, 153] The expression is not a valid conditional expression.
[153, 224] The query contains a malformed ending.
Anyone have an idea what exactly is wrong?
I have the following query:
UPDATE events e
SET
details = jsonb_set ( details, '{"data", "user_name"}', '"Resident"' ),
details = jsonb_set ( details, '{"data", "is_by_support"}', '"false"' ),
details = jsonb_set ( details, '{"data", "is_by_resident"}', '"true"' ),
updated_by = 1,
updated_on = now ()
FROM
test_req tr
WHERE
e.id = 12345 AND
AND e.data_reference_id = tr.id
AND e.event_type_id = 4
AND e.created_by = 2
AND e.updated_by = 2
AND e.details -> 'data' ->> 'user_name' = 'Test'
AND e.details -> 'data' ->> 'is_by_support' = 'true'
AND e.details -> 'data' ->> 'is_by_resident' = 'false';
After executing it gives me an error as
ERROR: multiple assignments to same column "details"
How to use multiple keys update in the same query? Is there any other way?
You cannot have the same column several times in the SET clause of an UPDATE. Why not do something like
SET details = jsonb_set(
jsonb_set(
jsonb_set(
details,
'{"data", "user_name"}',
'"Resident"'
),
'{"data", "is_by_support"}',
'"false"'
),
'{"data", "is_by_resident"}',
'"true"'
)
try this :
WITH list AS
(
SELECT e.id, jsonb_set(
jsonb_set(
jsonb_set(
details,
'{"data", "user_name"}',
'"Resident"'
),
'{"data", "is_by_support"}',
'"false"'
),
'{"data", "is_by_resident"}',
'"true"'
) AS sol
FROM events e
INNER JOIN test_req tr
ON e.data_reference_id = tr.id
WHERE e.id = 12345
AND e.event_type_id = 4
AND e.created_by = 2
AND e.updated_by = 2
AND e.details -> 'data' ->> 'user_name' = 'Test'
AND e.details -> 'data' ->> 'is_by_support' = 'true'
AND e.details -> 'data' ->> 'is_by_resident' = 'false'
)
UPDATE events e
SET details = l.sol,
updated_by = 1,
updated_on = now ()
FROM list AS l
WHERE e.id = l.id
I have an iteration logic that returns a query like this :
val baseQuery = s"select agg_id from quality.QUALITY_AGGREGATOR where job_id = 123 and level ="
val reprocessDate ="2018-10-24"
for( i <- 0 to level){
var currLevelSubQuery=""
if (i==0 ){
currLevelSubQuery= baseQuery + s"$i and agg_value >= '${reprocessDate}'"
}
else{
currLevelSubQuery= baseQuery + s"$i and parent_agg_id in ( $prevLevelSubQuery )"
}
prevLevelSubQuery= currLevelSubQuery
finalQuery = finalQuery + currLevelSubQuery + (if (i<level) " union " else "")
}
It returns a query of this nature for level = 2.
SELECT agg_id
FROM quality.quality_aggregator
WHERE job_id = 123
AND level = 0
AND agg_value >= '2018-10-24'
UNION
SELECT agg_id
FROM quality.quality_aggregator
WHERE job_id = 123
AND level = 1
AND parent_agg_id IN (SELECT agg_id
FROM quality.quality_aggregator
WHERE job_id = 123
AND level = 0
AND agg_value >= '2018-10-24')
UNION
SELECT agg_id
FROM quality.quality_aggregator
WHERE job_id = 123
AND level = 2
AND parent_agg_id IN (SELECT agg_id
FROM quality.quality_aggregator
WHERE job_id = 123
AND level = 1
AND parent_agg_id IN
(SELECT agg_id
FROM quality.quality_aggregator
WHERE job_id = 123
AND level = 0
AND agg_value >=
'2018-10-24'))
I am trying to convert it into a recursive logic like this
val baseQuery = s"select agg_id from quality.QUALITY_AGGREGATOR where job_id = 123 and level ="
val finalQuery = getAggIdSQLGenerator(2,"2018-10-24")
def getAggIdSQLGenerator(level : Int, reprocessDate:String):String={
if (level == 0)
( baseQuery + s"$level and agg_value >= '${reprocessDate}'")
else
{
val subQuery=getAggIdSQLGenerator(level-1 ,reprocessDate)
baseQuery + s"$level and parent_agg_id in (" +subQuery +") union "+ subQuery
}
}
But this is not yielding correct results. What am I missing?
This isn't recursive but I think it's a smaller, cleaner, implementation of what you're after.
val baseQuery = ".... level="
val levelRE = "level=(\\d+)".r.unanchored
val reprocessDate ="2018-10-24"
val av = s" and agg_value >= '${reprocessDate}'"
val pai = " and parent_agg_id in "
val itrs = 3
val query = List.iterate(s"${baseQuery}0$av", itrs) { prevStr =>
val level = prevStr match {
case levelRE(n) => n.toInt + 1
case _ => 0
}
s"$baseQuery$level$pai($prevStr)"
}.mkString(" union ")
The issue is you have added union on every query and you have concatenated subquery 2 times.
This gives your expected output.
val baseQuery = s"select agg_id from quality.QUALITY_AGGREGATOR where job_id = 123 and level ="
val finalQuery = getAggIdSQLGenerator(2, "2018-10-24")
def getAggIdSQLGenerator(level: Int, reprocessDate: String): String = {
if (level == 0) {
baseQuery + s" $level and agg_value >= '${reprocessDate}'"
} else {
val subQuery = getAggIdSQLGenerator(level - 1, reprocessDate)
baseQuery + s" $level and parent_agg_id in (" + subQuery + ")"
}
}
println("UNION " + finalQuery)
This is my database query
select v.FK_EQUIPMENT, sum(fuel) as fuel,v1.END_TIME_METER
from vp_reports v ,
(select distinct FK_EQUIPMENT,END_TIME_METER
from vp_reports v
where MODIFIED_ON in (select max(MODIFIED_ON)
from vp_reports
where END_TIME_METER is not null
group by FK_EQUIPMENT )) v1
where v.FK_EQUIPMENT = v1.FK_EQUIPMENT
group by v.FK_EQUIPMENT,v1.END_TIME_METER;
and I am writing the same in jpa
#Query("select new Reports (v.fkEquipment, sum(fuel) as fuel, v1.endTimeMeter) "
+ " from Reports v , "
+ " (select distinct fkEquipment, endTimeMeter from Reports v "
+ " where modifiedOn in ( select max(modifiedOn) from Reports where endTimeMeter is not null "
+ " group by fkEquipment)) v1 "
+ " where v.fkEquipment = v1.fkEquipment "
//+ " and v.mrfId= ?1 "
//+ " and v.shift in (?2) and v.fkStatusDei= ?3 and v.assignedDate between to_date(?4, 'yyyy-mm-dd') and to_date(?5, 'yyyy-mm-dd') "
+ " GROUP BY v.fkEquipment,v1.endTimeMeter ")
List<Reports> findByMrfIdAndShiftAndFkStatusDeiAndAssignedDate(String mrfId, String shift, long fkStatusDei, String from, String to);
and getting below error -
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException:
unexpected token: ( near line 1, column 107 [select new Reports
(v.fkEquipment, sum(fuel) as fuel, v1.endTimeMeter) from
com.dei.domain.Reports v , (select distinct fkEquipment,
endTimeMeter from com.dei.domain.Reports v where modifiedOn in (
select max(modifiedOn) from com.dei.domain.Reports where endTimeMeter
is not null group by fkEquipment)) v1 where v.fkEquipment =
v1.fkEquipment GROUP BY v.fkEquipment,v1.endTimeMeter ] at
org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:91)
at
org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:109)
at
org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:304)
at
org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:203)
Could you please help me ? or how do I convert my DB query to JPQL?
$query = "select (select count(a.serial_no) from tra2 a where a.model_no = ".$id." and a.flag = cast(3 as character varying) + (select count(a.serial_no) from stk a where a.model_no = ".$id." and a.trans_id is NULL)as qty)";
$result = $this->db->query($query);
return $result->result();
When i run the query
ERROR: syntax error at or near "as"
LINE 1: ...ck a where a.model_no = K258 and a.trans_id is NULL)as qty)
Add '' (quotes) on your WHERE clauses. I guess the data type is VARCHAR so you have to use quotes in your query
Like this
.... WHERE a.model_no = '" . $id . "' AND ...
The end of the quest must be:
...a.trans_id is NULL)) as qty"
Currently You have some like this
select (select 1 + 2 as qty)
but You want
select (select 1 + 2) as qty