jpql - How can I join tables with conditions? - spring

#Query("select distinct b from Book b" +
" left join fetch b.reviews r" +
" left join fetch r.user")
List<Book> findAllWithFiveReviews();
There are 3 tables - books, reviews, users.
A book has reviews and each review has an user(the review's writer)
What I want to do is to fetch all books' data with recent reviews(maximum 5 reviews for each book) by adding some codes to the query.
Is it possible to fetch the data with single query? Or should I use a different approach?

I suggest that using Repository methods or CriteriaBuilder API instead of JPQL or Native Query.

Related

How to extend 'join' query in elastic-search?

As so far, elasticsearch is not support join query.
Offical documents give several suggestions to do join query, which may be a little complicated and not easy to use.
https://www.elastic.co/guide/en/elasticsearch/reference/current/joining-queries.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/relations.html
opensearch provide SQL search plugin to support two indices join query.
https://opensearch.org/docs/latest/search-plugins/sql/complex/
We can write such sql query in opensearch:
SELECT
a.account_number, a.firstname, a.lastname,
e.id, e.name
FROM accounts a
JOIN employees_nested e
ON a.account_number = e.id
How to extend this ability to elastic search so that we can write queries to join two indices?
Thank you.

Hibernate, Order by count of subquery on ManyToMany using Predicates

I have a query written using Predicates in Hibernate and I need to add a subquery on a join table to count the number of joins and order by the number of joins where they exist in an array of ids.
The join table is a ManyToMany relation.
I am using flyway to setup the table schema, so while the join table exists in the database, a join model is not needed in Hibernate to join the 2 related models therefore no join model exists.
I don't care about retrieving these related models, I just want the number of joins so that I can order by them.
The following is PostGreSQL, which works. I need to convert the following PSQL into a Predicate based query:
SELECT u.*, COUNT(jui.interest_id) AS juiCount
FROM "user" u
LEFT JOIN (
SELECT ui.user_id, ui.interest_id
FROM user_interest ui
WHERE ui.interest_id IN (?)
) AS jui ON u.id = jui.user_id
GROUP BY u.id
ORDER BY juiCount DESC
Where the ids provided for the IN condition are passed into the subquery. The above query is in PostGreSQL.
Working with what I have so far:
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<User> q = b.createQuery(User.class);
Root<User> u = q.from(User.class);
// This doesn't make sense because this is not a join table
// Subquery<Interest> sq = q.subquery(Interest.class)
// Root<Interest> squi = sq.from(Interest.class);
// sq.select(squi);
// sq.where(b.in("interest_id", new LiteralExpression<Long[]>((CriteriaBuilderImpl) b, interestIds)));
q.orderBy(
// b.desc(b.tuple(u, b.count(squi))),
b.asc(u.get(User_.id))
);
q.where(p);
return em
.createQuery(q)
.getResultList();
Everything I have managed to find doesn't quite seem to fit right given that they are not using ManyToMany in the use of q.subquery() in their example.
Anyone can help fill in the blanks on this please?

Linq query for one to many

My question involves MVC + Linq query. I will try to make it simple without going into the details of the Model, View, etc.. Say I have 2 tables T1 & T2. T1 holds restaurants details & T2 holds restaurants image paths. T2 rows contain restaurantID. Now if T2 has more than one rows of image paths for a Restaurant and I only need the first image path from T2 in the linq query how would I form such query? I tried to simplify the question as in fact I have 6 table joins related to the Restaurants in the query. I formed a view model which only contains the fields I want to display. I am trying to populate the view model in the controller & the query is in the controller obviously.
When I join T2 to the query, I get all the Restaurants details together with the images. But the view repeats the same Restaurant as many times as the number of table rows in T2 which is not what I want. This is the problem from the way I set the query. The query uses joins. I only need the first row from T2 while I get all from the Restaurant details. I failed to find an example for such requirement on the web so far. Your directions will be much appreciated.
Serhat Albayoglu
On your join you can use an into and then in the select you can select the FirstOrDefault
var query = from t in context.T1
join t2 in context.T2 on t.Id equals t2.RestaurantID into tgroup
select
{
t2.FirstOrDefault().path
};

Dynamics CRM 2011 - Filtering LINQ query with outer joins

I have a requirement to query for records in CRM that don't have a related entity of a certain type. Normally, I would do this with an Left Outer Join, then filter for all the rows that have NULLs in the right-hand side.
For example:
var query = from c in orgContext.CreateQuery<Contact>()
join aj in orgContext.CreateQuery<Account>()
on c.ContactId equals aj.PrimaryContactId.Id
into wonk
from a in wonk.DefaultIfEmpty()
where a.Name == null
select new Contact
{
FirstName = c.FirstName,
LastName = c.LastName,
};
This should return me any Contats that are not the Primary Contact of an account. However, this query ends up returning all contacts...! When you look at the SQL that gets generated in SQL Profiler it comes out like this:
SELECT cnt.FirstName, cnt.LastName
FROM Contact as cnt
LEFT OUTER JOIN Account AS acct
ON cnt.ContactId = acct.PrimaryContactId AND acct.Name is NULL
So, I get the Left Join OK, but the filter is on the Join clause, and not in a WHERE clause.and not as it should, like this:
SELECT cnt.FirstName, cnt.LastName
FROM Contact as cnt
LEFT OUTER JOIN Account AS acct
ON cnt.ContactId = acct.PrimaryContactId
WHERE acct.Name is NULL
Clearly, the results from this query are very different! Is there a way to get the query on CRM to generate the correct SQL?
Is this a limitation of the underlying FetchXML request?
Unfortunately, this is a limitation of CRM's LINQ and FetchXML implementations. This page from the SDK states outer joins are not supported:
http://technet.microsoft.com/en-us/library/gg328328.aspx
And while I can't find an official document, there are a lot of results out there for people mentioning FetchXML does not support left outer joins, for example:
http://gtcrm.wordpress.com/2011/03/24/fetch-xml-reports-for-crm-2011-online/
Try this:
var query = from c in orgContext.CreateQuery<Contact>()
where orgContext.CreateQuery<Account>().All(aj => c.ContactId != aj.PrimaryContactId.Id)
select new Contact
{
FirstName = c.FirstName,
LastName = c.LastName,
};
If you don't need to update the entity (e.g. to process all the corresponding validation rules and workflow steps), you can write less-ugly and more efficient queries by hitting the SQL Server directly.
Per CRM's pattern, the views take care of most of the common joins for you. For instance, the dbo.ContactBase and dbo.ContactExtensionBase tables are already joined for you in the view dbo.Contact. The AccountName is already there (called AccountIdName for some bizarre reason, but at least it's there).

Entity Framework 4 generated queries are joining full tables

I have two entities: Master and Details.
When I query them, the resulting query to database is:
SELECT [Extent2]."needed columns listed here", [Extent1]."needed columns listed here"
FROM (SELECT * [Details]."all columns listed here"...
FROM [dbo].[Details] AS [Details]) AS [Extent1]
LEFT OUTER JOIN [dbo].[Master] AS [Extent2] ON [Extent1].[key] = [Extent2].[key]
WHERE [Extent1].[filterColumn] = #p__linq__0
My question is: why not the filter is in the inner query? How can I get this query? I've tried a lot of EF and Linq expressions.
What I need is something like:
SELECT <anything needed>
FROM Master LEFT JOIN Details ON Master.key = Details.Key
WHERE filterColumn = #param
I'm having a full sequential scan in both tables, and in my production environment, I have milions of rows in each table.
Thanks a lot !!
Sometimes The entity Framework does not produce the best query. You can do a few of the following to optimize.
Modify the linq statement (test with
LINQPad)
Create a stored proc and map the stored proc to return an entity
Create a view that handles the join and map the view to a new
entity

Resources