SELECT with JOIN And SUM in JPQL - mysql

I wanna do a query for extract information in a dashboard. I have two entities: User and Post, they are a manytomany relation. In my query, I wanna get the post information and the number of users by rol in each post.
I have tried this query, and it is working, but when there is a post without users, it isn't coming in the resultset, and it should be "| post1 | information | 0 | 0 |".
#Query("SELECT new com.project.dto.DashboardDTO("
+ "post.title, "
+ "post.information, "
+ "SUM(CASE WHEN u.rol = 0 THEN 1 ELSE 0 END), "
+ "SUM(CASE WHEN u.rol = 1 THEN 1 ELSE 0 END)) "
+ "FROM Post post JOIN post.users u "
+ "GROUP BY post.title, post.information")
Page<DashboardDTO> getDashboard(Pageable pageable);
What have I to fix?

You need to use left join instead of join, and you'll get the desired result.
Also if you need to get the summarization details for each post, you can group by the post id instead of (title, information) because both of them functionally depend on the id.
The query would be:
#Query("SELECT new com.project.dto.DashboardDTO("
+ "post.title, "
+ "post.information, "
+ "SUM(CASE WHEN u.rol = 0 THEN 1 ELSE 0 END), "
+ "SUM(CASE WHEN u.rol = 1 THEN 1 ELSE 0 END)) "
+ "FROM Post post LEFT JOIN post.users u "
+ "GROUP BY post")
Page<DashboardDTO> getDashboard(Pageable pageable);

Related

Mysql Query With Like Operator and order by keyword giving empty records in spring boot api

native Query I Wrote in My Repository
If i remove order by condition in the below query , it is giving some records but i want it in some order so i added order by condition then it not showing records only . but the same mysql query with order by condition is giving some records in mysql workbench.
#Query(value = "SELECT l.id AS id,l.first_name AS firstName,l.last_name AS lastName,"
+ " l.email AS email,l.phone AS phone,l.place AS place,l.course_id AS courseId,"
+ " c.name AS courseName,l.source AS source,l.enquiry_for AS enquiryFor,"
+ " l.appointment_date AS appointmentDate,l.description AS description,"
+ " l.discount AS discount,l.status AS status,l.assignee_id AS assigneeId,"
+ " ase.first_name AS assigneeFirstName,ase.last_name AS assigneeLastName,"
+ " l.assignor_id AS assignorId,asr.first_name AS assignorFirstName,"
+ " asr.last_name AS assignorLastName,l.active AS active,l.created_date AS createdDate,"
+ " l.updated_date AS updatedDate,(SELECT comments FROM reviews where created_date IN"
+ " (SELECT MAX(created_date) from reviews where lead_id=l.id)) AS latestComment FROM "
+ " leads l JOIN users AS ase ON l.assignee_id = ase.id JOIN users AS asr ON "
+ " l.assignor_id = asr.id JOIN courses AS c ON l.course_id =c.id WHERE l.status!='Draft'"
+ " AND (l.first_name LIKE '%:keyword%' OR l.last_name LIKE '%:keyword%' OR l.phone LIKE"
+ " '%:keyword%') ORDER BY -l.appointment_date DESC,l.created_date ASC", nativeQuery=true)
List<Leads> searchLeadsForAdmin(#Param("keyword") String searchKeyword);
i don't know Where am i going wrong , attached image below mysql query result came in workbench.
I found the answer to my question. It was a concatenation issue. In the second last line of my query after 'l.phone LIKE' I added the value in the next line.
+ " AND l.first_name LIKE %:keyword% OR l.last_name LIKE %:keyword% OR "
+ " l.phone LIKE %:keyword% ORDER BY -l.appointment_date DESC,"
+ " l.created_date ASC", nativeQuery = true)
The above query works.

How to add SELECT TOP (CASE WHEN user=#{username} THEN 100 ELSE 0 END) PERCENT * FROM (SELECT .... )?

My goal is to return either all of the row or just an empty array [] if "not one row" have column user with value #{username}.
This is the SQL SELECT statement
#Select("SELECT * FROM ( SELECT user_detail.user, user_detail.name, channel_member.role " +
"FROM user_detail " +
"JOIN channel_member ON user_detail.user=channel_member.user " +
"AND channel_member.uuid=#{channelUuid} )")
List<MemberModel> getChannelDetail(String username, String channelUuid);
My goal is to change the 100 PERCENT to 0 PERCENT if "not one row" have column user with value of #{username}
What I've tried
Add SELECT TOP (CASE WHEN user=#{username} THEN 100 ELSE 0 END) PERCENT ...
#Select("SELECT * FROM ( SELECT user_detail.user, user_detail.name, channel_member.role " +
"FROM user_detail " +
"JOIN channel_member ON user_detail.user=channel_member.user " +
"AND channel_member.uuid=#{channelUuid} ) " +
"LIMIT CASE WHEN user=#{username} THEN ALL ELSE 0 END")
List<MemberModel> getChannelDetail(String username, String channelUuid);
But it throws an error
Column "USER" not found; SQL statement:

[21000][1242] Subquery returns more than 1 row

My Query:
entityManager.createQuery("SELECT " +
"q.id, " +
"q.title, " +
"q.user.fullName, " +
"q.user.reputationCount, " +
"q.viewCount, " +
"q.countValuable, " +
"q.persistDateTime, " +
"t.id, " +
"t.name, " +
"t.description, " +
"(SELECT COUNT (a) FROM Answer a WHERE a.question.id = q.id), " +
"(SELECT a.isHelpful FROM Answer a WHERE a.question.id = q.id) " +
"FROM Question q JOIN q.tags t")
Here I get the error - [21000][1242] Subquery returns more than 1 row
By the method of exceptions, I determined that the error in this query string:
"(SELECT a.isHelpful FROM Answer a WHERE a.question.id = q.id) "
How to make the correct request so that there is no this error? Thank!
Two common ways are aggregation and limiting:
(SELECT MAX(a.isHelpful) FROM Answer a WHERE a.question.id = q.id)
(SELECT a.isHelpful FROM Answer a WHERE a.question.id = q.id LIMIT 1)
However, those are really just hacks to get around an "issue" with the data. I put issue in quotes, but the real issue is probably your understanding of data and not the data itself.
You should understand why there are duplicates. Then decide which value you want. And implement the correct logic for what you want.
Subquery returns more than 1 row, this simply means that your query is not returning a single row for the outer select statement to work.
"(SELECT a.isHelpful FROM Answer a WHERE a.question.id = q.id) "
you have to apply a set of conditions to filter out your data uniquely or use joins to combine your table Answer and Question and then filter data accordingly.
you can also group each row data in one column by GROUP_CONCAT Mysql function like this :
"(SELECT GROUP_CONCAT(a.isHelpful) FROM Answer a WHERE a.question.id = q.id) "
Although GROUP_CONCAT is not available in Mysql, for that you can also bind SQL function in hibernate as described in this post.
After a day of various trial and error, I found the following solution, I hope someone will broaden their horizons and help in solving their problem:
entityManager.createQuery("SELECT " +
"q.id, " +
"q.title, " +
"q.user.fullName, " +
"q.user.reputationCount, " +
"q.viewCount, " +
"q.countValuable, " +
"q.persistDateTime, " +
"t.id, " +
"t.name, " +
"t.description, " +
"(SELECT COUNT (a) FROM Answer a WHERE a.question.id = q.id), " +
"(SELECT CASE WHEN MAX (a.isHelpful) > 0 THEN true ELSE false END FROM Answer a WHERE a.question.id = q.id) " +
"FROM Question q JOIN q.tags t")

Why adding SUM changes the number of retrieved rows?

I have this sql which gives me 6 rows without SUM clause (sur can give more if condition is true)
SELECT id, prodname, prodid, st_date, montant, tvaval, quantite, status, factureno
FROM StockData WHERE " + VenteWhere + " ORDER BY " + Order_by + " " + SortDir + "
PS: VenteWhere, Order_by abd SortDir are the variables.
BUt when I add SUM(quantite) I get only one row. Is there a way to have 6 rows data and the sum of 6 rows or I have to do another query for getting it
I think you can use
SELECT id, prodname, prodid, st_date, montant, tvaval, SUM(quantite), status, factureno
FROM StockData
WHERE " + VenteWhere + "
ORDER BY " + Order_by + " " + SortDir + "
GROUP BY xxxxx
Where xxxxx represents the variable you want to group by per row.
Summing will remove the rows its sums over and only display the sum itself. So you have to group by some variable to make it split the results over that variables 'occurence'

Query for choose all orders from all restaurants for the current day

How can I write a mysql query that will choose all the orders of all restaurants for the current day?
Some restaurants may close after 24:00.
So I have three tables:
restaurants with some fields [id, ]
orders with some fields [id, resid, orderdate, ]
hours with some fields [id, resid, day, open, close] the day is a number from 0-6, the open and close are time between 00:00:00 and 23:59:59
Thank you
This is what about i need
SELECT b.*
FROM restaurants a, orders b, hours c
WHERE a.id=b.resid
AND a.id=c.resid
---- here i need the code that will choose the orders for the current working day of the restaurant, but the current working day may include some orders from the previous calendar day if the restaurant close after 24:00
Is this what you want?
select o.*
from orders o
where o.orderdate = curdate();
If not, can you modify your question to better explain what you want?
Because you did not give much information, so I make 2 assumption here
Assumption 1: You run this query at 1AM and want to get all order your 1AM yesterday till now
Assumption 2: No restaurant open 24h day
hours.day = WEEKDAY(SUBDATE(CURDATE(), 1)
If hours.close < hours.open mean restaurant open from YESTERDAY + open_time to TODAY + close_time, otherwise it is open and close on YESTERDAY
STR_TO_DATE(CONCAT(DATE_FORMAT(SUBDATE(CURDATE(), CASE WHEN c.close < c.open THEN 1 ELSE 0 END), '%Y%m%d'), c.close), '%Y%m%d%T')
So your query is something like
SELECT b.*
FROM restaurants a, orders b
WHERE a.id=b.resid
AND a.id in (
select c.resid
from hours c
where c.day = WEEKDAY(SUBDATE(CURDATE(), 1)
and STR_TO_DATE(CONCAT(DATE_FORMAT(SUBDATE(CURDATE(), 1), '%Y%m%d'), c.open), '%Y%m%d%T') > SUBDATE(CURDATE(), 1)
and STR_TO_DATE(CONCAT(DATE_FORMAT(SUBDATE(CURDATE(), CASE WHEN c.close < c.open THEN 1 ELSE 0 END), '%Y%m%d'), c.close), '%Y%m%d%T') <= CURDATE()
)
I'm not sure about orders.orderdate, so you should update your filter on orders table to get correct data you want.
Hope this help
The solution is
" SELECT b.*".
" FROM orders b, rests a, times c ".
" WHERE a.id=b.resid ".
" AND a.id=c.resid ".
" AND (".
"( c.day=dayofweek(subdate(current_date, 1))-1 " .
" AND c.close < c.open " .
" AND c.close> TIME(NOW())" .
" AND b.orderdate>= CONCAT(subdate(current_date, 1),' ',c.open) )" .
" OR " .
"( c.day=dayofweek(current_date)-1 " .
" AND c.close >= c.open " .
" AND c.close> TIME(NOW())" .
" AND b.orderdate>= CONCAT(current_date,' ',c.open) )" .
" OR " .
"( c.day=dayofweek(current_date)-1 " .
" AND c.close < c.open " .
" AND CONCAT(ADDDATE(CURRENT_DATE, 1),' ',c.close)> TIME(NOW())" .
" AND b.orderdate>= CONCAT(current_date,' ',c.open) )" .
")";