I need to use window functions within a Spring Data Repository, is
this possible?
I am now using java spring maven and I have no knowledge about the entity table partition in JPA.
My SQL Query
select
b.q_stop_id as q_stop_id,
b.q_work_day as q_work_day,
b.q_work_end as q_work_end,
b.q_mc_num as q_mc_num,
b.q_mc_name as q_mc_name,
b.Hnbn as q_hnbn,
b.q_koku as q_koku,
b.q_stop_st_time as q_stop_st_time,
b.q_stop_en_time as q_stop_en_time,
b.q_stop_time_s as q_stop_time_s,
b.q_stop_maj_code as q_stop_maj_code,
b.q_stop_major as q_stop_major,
b.q_stop_num as q_stop_num,
b.q_stop_minor as q_stop_minor,
b.q_pause_flag as q_pause_flag
from
(
select ROW_NUMBER() OVER (PARTITION BY a.rnk
ORDER BY a.q_stop_st_time,a.q_stop_en_time) AS RowNo,COUNT(*) OVER () as cnt,*
from (
select DENSE_RANK() OVER(PARTITION BY proL.q_set_hnbn ORDER BY stL.q_stop_st_time,stL.q_stop_en_time DESC) as rnk,case when proL.q_set_hnbn is not null and proL.q_set_hnbn !='' then proL.q_set_hnbn else proL.q_hnbn end as Hnbn ,proL.q_set_hnbn as setHnbn, stL.q_stop_id as q_stop_id,wk.q_work_day as q_work_day,wk.q_work_end as q_work_end,mc.q_mc_num as q_mc_num,mc.q_mc_name as q_mc_name,proL.q_hnbn as q_hnbn,proL.q_koku as q_koku,stL.q_stop_st_time as q_stop_st_time,stL.q_stop_en_time as q_stop_en_time,stL.q_stop_time_s as q_stop_time_s,mst.q_stop_maj_code as q_stop_maj_code,mst.q_stop_major as q_stop_major,mst.q_stop_num as q_stop_num,mst.q_stop_minor as q_stop_minor,
mst.q_pause_flag as q_pause_flag
from T_STOP_LOG stL inner join M_stop_item mst on stL.q_stop_num=mst.q_stop_num
inner join T_work_log wk on stL.q_work_id=wk.q_work_id
inner join T_prod_log proL on wk.q_work_id =proL.q_work_id
inner join M_mc mc on wk.q_mc_num=mc.q_mc_num
left join T_malfunction_repair_log r on r.q_stop_id=stL.q_stop_id
where wk.q_work_day >='2021-04-19 00:00:00.000' and
wk.q_work_end<='2021-04-20 23:59:59.000' and mc.q_mc_num='1200' )a
)b where b.RowNo=1 or b.RowNo=2
> I found the solution by using JPA nativeQuery = true
#Query(value = "select " + "b.q_stop_id as q_stop_id," + "b.q_work_day as q_work_day,"
+ "b.q_work_end as q_work_end," + "b.q_mc_num as q_mc_num," + "b.q_mc_name as q_mc_name,"
+ "b.Hnbn as q_hnbn," + "b.q_koku as q_koku," + "b.q_stop_st_time as q_stop_st_time,"
+ "b.q_stop_en_time as q_stop_en_time," + "b.q_stop_time_s as q_stop_time_s,"
+ "b.q_stop_maj_code as q_stop_maj_code," + "b.q_stop_major as q_stop_major,"
+ "b.q_stop_num as q_stop_num," + "b.q_stop_minor as q_stop_minor," + "b.q_pause_flag as q_pause_flag "
+ "from" + "(" + "select ROW_NUMBER() OVER (PARTITION BY a.rnk "
+ "ORDER BY a.q_stop_st_time,a.q_stop_en_time) AS RowNo,COUNT(*) OVER () as cnt,* "
+ "from (select DENSE_RANK() OVER(PARTITION BY proL.q_set_hnbn ORDER BY stL.q_stop_st_time,stL.q_stop_en_time DESC) as rnk,case when proL.q_set_hnbn is not null and proL.q_set_hnbn !='' then proL.q_set_hnbn else proL.q_hnbn end as Hnbn ,proL.q_set_hnbn as setHnbn,stL.q_stop_id as q_stop_id,wk.q_work_day as q_work_day,wk.q_work_end as q_work_end,mc.q_mc_num as q_mc_num,mc.q_mc_name as q_mc_name,proL.q_hnbn as q_hnbn,proL.q_koku as q_koku,stL.q_stop_st_time as q_stop_st_time,stL.q_stop_en_time as q_stop_en_time,stL.q_stop_time_s as q_stop_time_s,mst.q_stop_maj_code as q_stop_maj_code,mst.q_stop_major as q_stop_major,mst.q_stop_num as q_stop_num,mst.q_stop_minor as q_stop_minor,"
+ "mst.q_pause_flag as q_pause_flag "
+ "from T_STOP_LOG stL inner join M_stop_item mst on stL.q_stop_num=mst.q_stop_num "
+ "inner join T_work_log wk on stL.q_work_id=wk.q_work_id "
+ "inner join T_prod_log proL on wk.q_work_id =proL.q_work_id "
+ "inner join M_mc mc on wk.q_mc_num=mc.q_mc_num "
+ "left join T_malfunction_repair_log r on r.q_stop_id=stL.q_stop_id "
+ "where wk.q_work_day >=:workDay and wk.q_work_end<=:workEnd and mc.q_mc_num=:kiban)a "
+ ")b where b.RowNo=1 or b.RowNo=2", nativeQuery = true)
I have working query in PostgreSQL:
select s.id, s.seat_number as available_seat, s.row_number as available_row, rm.room_name as screening_room
from seats s
join rooms rm on rm.id=s.room_id
left join (
select r.seat_id from reserved_seats r
join reservations res on res.id=r.reservation_id AND res.screening_id = 3 ) res on res.seat_id=s.id
where res.seat_id is null AND s.room_id=3
ORDER BY s.id;
But I make mistakes translating it into the JPA query language.
Can I use nested SELECTs in JPQL?
The answer is to use native query:
#Query(value =
"SELECT s.id seatId, s.seat_number availableSeat, " +
"s.row_number availableRow, rm.name screeningRoom \n" +
"FROM seats s\n" +
"JOIN rooms rm on rm.id=s.room_id\n" +
" LEFT JOIN (\n" +
" SELECT r.seat_id FROM reserved_seats r\n" +
" JOIN reservations res ON res.id=r.reservation_id " +
" AND res.screening_id = :screeningId) res ON res.seat_id=s.id\n" +
"WHERE res.seat_id IS NULL AND s.room_id=:roomId AND s.row_number=:rowNumber\n" +
"ORDER BY s.id;", nativeQuery = true)
The answer is to use native query:
#Query(value =
"SELECT s.id seatId, s.seat_number availableSeat, " +
"s.row_number availableRow, rm.name screeningRoom \n" +
"FROM seats s\n" +
"JOIN rooms rm on rm.id=s.room_id\n" +
" LEFT JOIN (\n" +
" SELECT r.seat_id FROM reserved_seats r\n" +
" JOIN reservations res ON res.id=r.reservation_id " +
" AND res.screening_id = :screeningId) res ON res.seat_id=s.id\n" +
"WHERE res.seat_id IS NULL AND s.room_id=:roomId AND s.row_number=:rowNumber\n" +
"ORDER BY s.id;", nativeQuery = true)
I have this Query in my JPA repository - and it works EXCEPT the " order by " part. Am i doing this wrong ? is it different in hql ?
#Query(value = "select wm.WagerIdentification, wm.BoardNumber, wm.MarkSequenceNumber, wm.MarkNumber," +
" pt.CouponTypeIdentification, pt.WagerBoardQuickPickMarksBoard " +
"from WagerBoard wb " +
"inner join wb.listOfWagerMarks wm " +
"inner join wb.poolgameTransaction pt " +
"where wb.WagerIdentification = wm.WagerIdentification and wb.BoardNumber = wm.BoardNumber and wb.GameIdentification = wm.GameIdentification and wm.meta_IsCurrent = 1 " +
"and wb.TransactionIdentification = pt.TransactionIdentification and pt.meta_IsCurrent = 1 " +
"and wb.meta_IsCurrent = 1 order by wm.WagerIdentification asc, wm.BoardNumber asc, wm.MarkNumber asc")
Instead of ordering result within the #Query, you can add a method parameter of type Sort, like in Spring Data JPA reference
I want to retrieve all the records in One database hit and for that, I am using join fetch statements below is my Query
String q = "SELECT oneChat from " + Chat.class.getName() + " oneChat "
+ " join fetch oneChat.user1 "
+ " join fetch oneChat.user2 "
+ " join fetch oneChat.user3 "
+ " join fetch oneChat.groupData "
+ "where oneChat.dmlStatus != :dmlStatusValue"
+ " AND group_id = :groupIdValue" + " AND reference_id = 0"
+ " AND root_chat_id = oneChat.chatId";
There are total 4 foreign keys/Joins in my table so I added the join fetch statement but its not working i.e. not returning anything how ever if I remove the join fetch statements I get the result set. My Fetch on table joins is by default Eager ( didn't changed it to Lazy).
Also there's no sql syntax error in the Log file. Am I missing anything ?
Update:
It is because the second join i.e. user2 is returning null so I wasn't getting any data. Now if anyone could tell me how can I counter this, the query should be independent it shouldn't rely on data.
IF you want to return results regardless of data being present on the dependencies, then you should use left join instead of inner join (join fetch is equal to inner join fetch):
"SELECT oneChat from " + Chat.class.getName() + " oneChat "
+ " left join fetch oneChat.user1 "
+ " left join fetch oneChat.user2 "
+ " left join fetch oneChat.user3 "
+ " left join fetch oneChat.groupData "
+ "where oneChat.dmlStatus != :dmlStatusValue"
+ " AND group_id = :groupIdValue" + " AND reference_id = 0"
+ " AND root_chat_id = oneChat.chatId";
Now when the OneChat does not have any user2 dependency on the database, the query will still return results regardless of that.
Just on the side.. if you are using prefixed, then try to add prefixes to group_id and root_chat_id fields in the where clause for clarity.
I experience some strange results working with SQLite and JDBC (via JOOQ actually, but this problem can be reproduced by executing the query string manually via JDBC). My database consists of a three tables including a many-to-many and one-to-many relationship. I try to select all values of the 'main' table and join all needed values out of the relationship tables:
SELECT location.name,
world.world,
player.player
FROM location
JOIN world
ON location."world-id" = world."world-id"
LEFT OUTER JOIN (location2player
JOIN player
ON location2player."player-id" = player."player-id")
ON location."location-id" = location2player."location-id"
Within JDBC this query fails:
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such column: player.player)
When I execute the query in an external SQLite editor such as SQLite Manager for Firefox it works as expected.
I work with sqlite-jdbc-3.7.2 which I cannot change. For reference, the JOOQ query is:
create.select(LOCATION.NAME,WORLD.WORLD_,PLAYER.PLAYER_)
.from(LOCATION
.join(WORLD)
.on(LOCATION.WORLD_ID.eq(WORLD.WORLD_ID)
)
.leftOuterJoin(LOCATION2PLAYER
.join(PLAYER)
.onKey()
)
.on(LOCATION.LOCATION_ID.eq(LOCATION2PLAYER.LOCATION_ID)
)
.fetch()
Why fails this query in JDBC and how am I supposed to fix it?
While I think that you wrote valid ANSI SQL, it may well be that SQLite interprets your statement slightly differently. But you don't really need to nest joins the way you do. Try this insted:
SELECT location.name,
world.world,
player.player
FROM location
JOIN world
ON location."world-id" = world."world-id"
LEFT OUTER JOIN location2player
ON location."location-id" = location2player."location-id"
LEFT OUTER JOIN player
ON location2player."player-id" = player."player-id"
I was able to recreate your issue under sqlite-jdbc-3.7.2 using
sql =
"SELECT location.name, " +
"world.world, " +
"player.player " +
"FROM " +
"location " +
"JOIN world " +
"ON location.\"world-id\" = world.\"world-id\" " +
"LEFT OUTER JOIN (location2player " +
"JOIN " +
"player " +
"ON location2player.\"player-id\" = player.\"player-id\") " +
"ON location.\"location-id\" = location2player.\"location-id\"";
The problem appears to be that the location2player and player tables are "hidden" inside the parentheses () of the sub-join and are unavailable to the initial column list and the final ON clause. The following statement avoids that problem by giving the subquery an alias and using the alias name in those two places:
sql =
"SELECT " +
"location.name, " +
"world.world, " +
"playerlocation.player " +
"FROM " +
"location " +
"JOIN " +
"world " +
"ON location.\"world-id\" = world.\"world-id\" " +
"LEFT OUTER JOIN " +
"( " +
"SELECT location2player.\"location-id\", player.player " +
"FROM " +
"location2player " +
"JOIN " +
"player " +
"ON location2player.\"player-id\" = player.\"player-id\"" +
") AS playerlocation " +
"ON location.\"location-id\" = playerlocation.\"location-id\"";