I'm using spring data JPA and I want to write a SQL query in my repository.
I have a following SQL query (notice the LEFT JOIN):
SELECT * FROM institution LEFT JOIN
(select * from building_institutions where building_institutions.building_id = 1) as reserved_institutions
ON reserved_institutions.institutions_user_id = institution.user_id
WHERE reserved_institutions.institutions_user_id is null;
and i want to execute it in my InstitutionRepository which is as follows:
@Repository
public interface InstitutionRepository extends JpaRepository<Institution, Long>, PagingAndSortingRepository<Institution,Long> {
// doesn't work
//@Query("SELECT b.institutions as bi FROM Building b left join Institution i WHERE bi.building_id not in :id")
Page<Institution> findPotentialInstitutionsByBuildingId(@Param("id") Collection<Long> id, Pageable pageable);
// doesn't work
@Query(
value = "SELECT * FROM kits_nwt.institution LEFT JOIN\n" +
"(SELECT * FROM kits_nwt.building_institutions WHERE kits_nwt.building_institutions.building_id = ?1) AS reserved_institutions\n" +
"ON reserved_institutions.institutions_user_id = kits_nwt.institution.user_id\n" +
"WHERE reserved_institutions.institutions_user_id IS null ORDER BY ?#{#pageable}",
nativeQuery = true)
Page<Institution> findPotentialInstitutionsByBuildingId(Long userId, Pageable pageable);
}
So, I want to get all institutions which are not in building with certain ID (which I will send as a parameter).
Institutions:
Building institutions:
What I want: (in this query, the id is set on 1, for presentation purposes)
I have looked at many SO questions and answers (such as this one) but I haven't been able to figure out the solution.
So, how do I write this query so that I get what I want?
@KevinAnderson Currently, I'm trying with:
@Query(
value = "SELECT username, password, description, location, title, user_id FROM (institution INNER JOIN user ON institution.user_id = user.id) LEFT JOIN\n" +
"(SELECT * FROM building_institutions WHERE building_institutions.building_id = 1) AS reserved_institutions\n" +
"ON reserved_institutions.institutions_user_id = kits_nwt.institution.user_id\n" +
"WHERE reserved_institutions.institutions_user_id IS null ORDER BY ?#{#pageable}",
nativeQuery = true)
Page<Institution> findPotentialInstitutionsByBuildingId(Long userId, Pageable pageable);
And I'm getting this exception:
MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE) FROM building_institutions WHERE building_institutions.building_id = 1) A' at line 2
@StanislavL here it is:
The problem is that your query gets me the institution with ID 25 because it is in both building with ID 1 and building with ID 2. When you do a JOIN, you have 2 rows ON institution ID being 25 in both institution table and building_institutions table. Then, your WHERE condition removes one from those two rows and I get one row where instituiton ID is 25, and I don't want what.
Here is an image for the above:
@NamedQuery
but @Query
@Query
annotationI solved it...
The query needs to look like this:
@Query(
value = "SELECT * FROM \n" +
"(institution INNER JOIN user ON institution.user_id = user.id) \n" +
"LEFT JOIN \n" +
"(SELECT * FROM \n" +
"building_institutions \n" +
"WHERE building_id = :userId)\n" +
" AS reserved_institutions \n" +
"ON reserved_institutions.institutions_user_id = kits_nwt.institution.user_id \n" +
" where reserved_institutions.institutions_user_id IS null \n"
+ "ORDER BY ?#{#pageable}"
,
countQuery = "SELECT count(*) FROM \n" +
"(institution INNER JOIN user ON institution.user_id = user.id) \n" +
"LEFT JOIN \n" +
"(SELECT * FROM \n" +
"building_institutions \n" +
"WHERE building_id =:userId)\n" +
" AS reserved_institutions \n" +
"ON reserved_institutions.institutions_user_id = kits_nwt.institution.user_id \n" +
"where reserved_institutions.institutions_user_id IS null \n" +
"ORDER BY ?#{#pageable}",
nativeQuery = true)
Page<Institution> findPotentialInstitutionsByBuildingId(@Param("userId") Long userId, Pageable pageable);
I was getting the error at line 4 near WHERE, when my query looked like this:
@Query(
value = "SELECT username, password, description, location, title, user_id FROM (institution INNER JOIN user ON institution.user_id = user.id) LEFT JOIN\n" +
"(SELECT * FROM building_institutions WHERE building_institutions.building_id = 1) AS reserved_institutions\n" +
"ON reserved_institutions.institutions_user_id = kits_nwt.institution.user_id\n" +
"WHERE reserved_institutions.institutions_user_id IS null ORDER BY ?#{#pageable}",
nativeQuery = true)
Page<Institution> findPotentialInstitutionsByBuildingId(Long userId, Pageable pageable);
and that was because I didn't add the countQuery
parameter to the @Query
annotation.
Big thanks to all of you who tried to help.
I hope that I save someone else many hours of misery.
Cheers! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With