How to re-use result from a SELECT statement? - mysql

My goal is to re-use the result from a SELECT statement to be used in SQL EXISTS statement.
The general idea looks like this:
SELECT *
FROM table
WHERE col1=1
OR EXISTS (
SELECT 1 // this is an exact copy of the SELECT statement above.
FROM table
WHERE col=1
)
The actual SQL statement I am trying to reduce:
"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} " +
"WHERE user_detail.user=#{username} " +
"OR EXISTS ( " +
" SELECT 1" +
" FROM user_detail " +
" JOIN channel_member ON user_detail.user=channel_member.user " +
" AND channel_member.uuid=#{channelUuid} " +
" WHERE user_detail.user=#{username} " +
")"

You can only do this if your version of MySQL supports window functions, ie. version >= 8.0
You can use conditional window aggregation, like this:
SELECT *
FROM (
SELECT *, COUNT(CASE WHEN col1 = 1 THEN 1 END) OVER () AS CountMatches
FROM table
) t
WHERE CountMatches > 0;
Depending on the number of rows matching to non-matching, this may be more or less performant. You need to test.

This query:
SELECT *
FROM table
WHERE col1 = 1 OR
EXISTS (SELECT 1 // this is an exact copy of the SELECT statement above.
FROM table
WHERE col=1
)
Doesn't really make sense. It is saying to return all rows if col = 1 is in the table -- but then it filters to check if any row has col = 1. So it is equivalent to:
SELECT *
FROM table
WHERE (SELECT 1 FROM table t2 WHERE t2.col = 1);
I strongly suspect that you intend NOT EXISTS -- so get everything with 1. If there is no 1 then return everything:
SELECT *
FROM table
WHERE col1 = 1 OR
NOT EXISTS (SELECT 1 // this is an exact copy of the SELECT statement above.
FROM table
WHERE col = 1
);
This should work fine with tables -- and is in fact probably optimal with the right indexes.
If "table" is really a complex query, then you might consider window functions:
select t.*
from (select t.*,
sum( col = 1 ) as num_1s
from t
) t
where col = 1 or num_1s = 0;

If you want to use any conditional statement on the query you are running you will need to wrap the query and put it in a FROM statement and then run the conditional outside of the query, like so....
SELECT aliasName.*
FROM
(SELECT *
FROM table
WHERE col1=1) aliasName
WHERE EXISTS aliasName //this is the conditionl statement OUTSIDE of the query you built.
Let me know how you do...

For Mr./Ms. Barmar:
The idea
// Idea:
// If one of the row have col1 with value 1.
// Then return all of the row, or return empty []
// SELECT *
// FROM table
// WHERE col1=1
// OR EXISTS (
// SELECT 1
// FROM table
// WHERE col=1
// )
The solution
"WITH temp AS (" +
" 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} " +
") " +
"SELECT * " +
"FROM temp " +
"WHERE user=#{username} " +
" OR EXISTS ( " +
" SELECT 1" +
" FROM temp " +
" WHERE user=#{username} " +
" )"
The solution above use WITH clause as recommended by Mr./Ms. Barmar, I am posting this, so you can inspect whether this is logical or not.

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.

Why am I getting a "No value specified for parameter 2" error in Spring boot jdbc template

My sql query looks like:
select T.Col1
from (
select Past_Diagnoses_1 as Col1
from patienthistory
union
select Past_Diagnoses_2 as Col1
from patienthistory
union
select Past_Diagnoses_3 as Col1
from patienthistory
union
select Past_Diagnoses_4 as Col1
from patienthistory
) as T;
I keep getting an error on Spring which says No value specified for parameter 2
I am trying to union 4 columns together into 1 super long column.
This is a simplified code. I have 32 columns but for question I have shown 4
Java code :
public UserTemp findHistoryByID(Integer Patient_Number) {
String sql = "select T.Col1\n" +
"from (\n" +
" select Past_Diagnoses_1 as Col1\n" +
" from patienthistory\n" +
" union\n" +
" select Past_Diagnoses_2 as Col1\n" +
" from patienthistory\n" +
" union\n" +
" select Past_Diagnoses_3 as Col1\n" +
" from patienthistory\n" +
" union\n" +
" select Past_Diagnoses_4 as Col1\n" +
" from patienthistory\n" +
" union\n" +
" select Past_Diagnoses_5 as Col1\n" +
" from patienthistory\n"
" where Patient_Number = ?\n" +
" ) as T";
return jdbcTemplate.queryForObject(sql, new Object[]{Patient_Number}, (rs, rowNum) ->
new UserTemp(
rs.getString("T.Col1")
));
}

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")

DELETE query with adding TOP

I want to delete some records that are on the top by the date and time.
the error is near 2, (the value of no_of_recordss)
DELETE TOP " + no_of_recordss + " FROM [upload_news] WHERE [country]='" + countryy.Text + "' ORDER BY [upload_time] ASC"
Try like this
;WITH CTE AS
(
SELECT TOP " + no_of_recordss + " *
FROM [upload_news]
WHERE [country]='" + countryy.Text + "'
ORDER BY [upload_time] ASC
)
DELETE FROM CTE