How to create a query for a known value on a known field, with a known date between 2 unknown dates) - oracle

The task is to find a known value in the specified field. Condition: There is a system date or a date that I want to use. This date must be between 2 dates ( the fields where the dates are known), that is, you need to check all the dates in the database, + additional condition:
it is necessary that the found string had in itself a previously known field marked IS NULL
The code written in Sql, below working.
select b.* from nc_proc b where b.code_proc = 'S.2.2' and b.date_on >= '12-AUG-19' and b.d_off IS NULL and b.date_off > '12-AUG-19';
'12-AUG-19' is a variable that is sent to me(more precisely, I form it from the system time)
'S. 2. 2' is a variable that I get and which is the main search.
How to make a request ?
here is an example that tried to make
#Query(value = "SELECT b.* FROM nc_proc b WHERE b.code_proc = ?1 and b.date_on > ?2 and b.d_off IS NULL and b.date_off > ?2 ", nativeQuery = true)
List <NcProc> findByCodeProcList2 (String value, String systemDate);
This don't work.
Please tell me how to fix. And is it possible not to use the query manually, but to do with the built-in keywords spring data ? Then this option would be better.
Update
#Query(value = "SELECT b.* FROM nc_proc b WHERE b.code_proc = ?1 and ?2 b.date_on BETWEEN b.date_off and b.d_off IS NULL", nativeQuery = true)
List <NcProc> findByCodeProcList2 (String value, String systemDate);
Hibernate: SELECT b.* FROM nc_proc b WHERE b.code_proc = ? and ?
b.date_on BETWEEN b.date_off and b.d_off IS NULL
11:02:58:871 WARN http-nio-8080-exec-1
o.h.e.j.s.SqlExceptionHelper:137 - SQL Error: 920, SQLState: 42000
19-сентября-20 11:02:58:871 ERROR http-nio-8080-exec-1
o.h.e.j.s.SqlExceptionHelper:142 - ORA-00920: invalid relational operator
In addition, I was told that BETWEEN includes the left and right restriction, and it is necessary that the desired date was in the specified interval and is not equal to the left and right restriction.
Update
it's work
#Query(value = "select * from nc_proc where code_proc = ?1 " +
"and date_on <= TO_DATE(?2, 'yyyy-mm-dd HH24:MI:SS') " +
"and TO_DATE(?2, 'yyyy-mm-dd HH24:MI:SS ') < date_off " +
"and d_off IS NULL",
nativeQuery = true)
NcProc findByCodeProc(String codeProc, String systemDate);
I wanted not to use the native record in the future.
Who knows how to make an expression from the keywords spring-data ?

I can't help on the Spring side, but for your queries I think you want something like:
SELECT b.* FROM nc_proc b WHERE b.code_proc = ?1 AND b.date_on > ?2 AND b.date_off < ?2 AND b.d_off IS NULL
It's unclear from your question whether the dates go b.date_on > '12-AUG-19' > b.date_off or the other way around, b.date_on < '12-AUG-19' < b.date_off. So you might have to switch the > < operators.

Related

JPQL query with having oracle db

I am using jpql jpa eclipselink Following query wont work :
SELECT c FROM TableA c WHERE c.forumId = :forumId AND c.isDefault = true HAVING MAX (c.validFrom)
The error im getting "The expression is not a valid conditional expression"
The HAVING clause only works with a GROUP BY expression.
The HAVING clause allows for the results of a GROUP BY to be filtered.
Your question is:
i want o get max validFrom how can i make expression ot of this
But you can make a query without GROUP BY and HAVING to do what you want:
select c from TableA c WHERE c.validFrom = (
SELECT MAX(c2.validFrom)
FROM TableA c2
WHERE c2.Id = c.Id AND c.forumId = :forumId AND c.isDefault = true
)
If you would like to use GROUP BY and HAVING, you can do:
SELECT c FROM TableA c WHERE c.validFROM = (
SELECT MAX(validFROM)
FROM TableA
WHERE forumId = :forumId AND isDefault = true
GROUP BY validFROM
HAVING validFROM=c.validFROM
)

Pass date parameter to native query

A user can perform actions based on an occurrence value. When this value is equal to 'DAILY', I would like to retrieve all daily actions that have not been completed the last 24 hours.
The working SQL query:
SELECT distinct a.* FROM action as a LEFT OUTER JOIN history as h
ON a.id = h.action_id
AND h.user_id= <user> WHERE a.occurrence = 'DAILY' AND (h.id is NULL OR h.entry_date < TIMESTAMP 'yesterday')
The equivalent native query:
#Query(value =
"SELECT distinct a.* FROM action a "
+ "LEFT OUTER JOIN history h "
+ "ON a.id = h.action_id "
+ "AND h.user_id = :userId "
+ "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday) ", nativeQuery = true)
public List<Action> findAllAvailableActions(#Param("userId") Long userId, #Param("yesterday") ZonedDateTime yesterday);
How it is called in my service :
ZonedDateTime today = ZonedDateTime.now(ZoneOffset.UTC);
ZonedDateTime yesterday = today.minus(1,ChronoUnit.DAYS);
Long userId = userDTO.getId();
List<Action> result = actionRepositoryCustom.findAllAvailableActions(userId, yesterday);
However, I do get the wrong results in my tests (actions that have already been completed are returned). I am afraid this is linked to the date parameter. The attribute entry_date is declared as ZoneDateTime in my entity. What am I doing wrong ?
hibernate : 5.2.4
You can't pass a ZonedDateTime into a native SQL query. You need to convert it to Calendar:
#Query(value =
"SELECT distinct a.* FROM action a "
+ "LEFT OUTER JOIN history h "
+ "ON a.id = h.action_id "
+ "AND h.user_id = :userId "
+ "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday)", nativeQuery = true)
public List<Action> findAllAvailableActions(#Param("userId") Long userId, #Param("yesterday") Calendar yesterday);
And you can convert your ZonedDateTime this way:
public Calendar convertToDatabaseColumn(ZonedDateTime entityAttribute) {
if (entityAttribute == null) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(entityAttribute.toInstant().toEpochMilli());
calendar.setTimeZone(TimeZone.getTimeZone(entityAttribute.getZone()));
return calendar;
}
This approach is described here: link

simple join syntax not properly working

I'd like to show the number of records in the history table grouped by name of service
service(code,name)
history(id, code,....)
Please note that there is no relationship between the two table history and service, history stores the activity independently from the other tables
I have tested this sql query and it returns the expected result:
select s.name, count(*) from history c
join service s
on c.code=s.code
where c.state='INITIALE'
group by s.name
Actually, I'd like to write it in jpql, I did alike
Query query =entityManager.createQuery(" select s.name, count(*) from ServiceEntity s join"
+ " HistoryEntity c "
+ " where c.code=s.code and c.state='INITIALE'"
+ " group by c.name order by c.name"
);
I got this error : Path expected for join!....
Invalid path: 'c.code'....right-hand operand of a binary operator was null....unexpected end of subtree
Try this
Query query = entityManager.createQuery("select s.name, count(s) from ServiceEntity s, HistoryEntity c "
+ " where c.code = s.code and c.state = 'INITIALE'"
+ " group by s.name order by s.name"
);

jpql native query not setting parameter

#Repository
public interface GroupRepository extends JpaRepository<Group, String> {
//Other queries....
#Query(value = "with cte(group_id, parent_group_id, group_name) as( "
+ "select group_id, parent_group_id, group_name "
+ "from hea.hea_group "
+ "where group_id = ?1 "
+ "union all "
+ "select g.group_id, g.parent_group_id, g.group_name "
+ "from hea.hea_group g "
+ "inner join cte on cte.group_id = g.parent_group_id "
+ "where g.parent_group_id is not null "
+ ") select * from cte", nativeQuery = true)
List<Object> getChildGroups(String groupId);
}
Above is the query that I have written that should return the parent group and all of its children. The query does what it is suppose to do when I replace the ?1 with a hard coded group id value and change the method to have no parameters, but when I try to run it as above it returns nothing even though I'm passing in the exact same value that I was hard coding.
Below is the sql that is being generated by the query. When I replace the ? with a group id an run it on a test database it returns the results that it should.
with cte(group_id, parent_group_id, group_name) as( select
group_id,
parent_group_id,
group_name
from
hea.hea_group
where
group_id = ?
union
all select
g.group_id,
g.parent_group_id,
g.group_name
from
hea.hea_group g
inner join
cte
on cte.group_id = g.parent_group_id
where
g.parent_group_id is not null ) select
*
from
cte
The variables are zero based so ?0 is what you should use.

PL/SQL : Example for select and update the record based on certain rule

I have situation something like below...
select * from tableA A
if A.salary > 100 and A.years > 0 then
update tableA set A.level = '1' where A.id = id;
else if A.salary > 200 A.years > 1 then
update tableA set A.level = '2' where A.id = id;
else
update tableA set A.level = '0' where A.id = id;
end if
how i can implement this in PL/SQL? above situation is just an example.
You don't need to do this in PL/SQL; it can be done in a single UPDATE statement by using a CASE expression:
update tablea
set level = case when salary > 100 and years > 0 then 1
when salary > 200 and years > 1 then 2
else 0
end
It's worth noting that "level" is a reserved word (it's a psuedocolumn used for Oracle's hierarchical queries) and can cause problems if you use it. I'd choose something else if possible.

Resources