Inner join with more than one OR conditions in spring boot - spring

I am using spring boot specification and trying to execute a query that looks like this -
SELECT DISTINCT
p.name
FROM
partner p
INNER JOIN
detail d ON p.detail_id = d.id
INNER JOIN
account a ON d.account_id = a.id
OR d.crm_id = a.top_parent
OR d.crm_id = a.global_partner
I have used the code
Join<Partner, Detail> details = root.join("detail");
Join<Detail, Account> account = details.join("account");
Predicate global = cb.equal(details.get("crm_id "), account.get("top_parent"));
Predicate top = cb.equal(details.get("crm_id "), account.get("global_partner"));
account.on(cb.or(global, top));
However, it creates the query
SELECT DISTINCT
p.name
FROM
partner p
INNER JOIN
detail d ON p.detail_id = d.id
INNER JOIN
account a ON d.account_id = a.id
AND (d.crm_id = a.top_parent
OR d.crm_id = a.global_partner)
Notice the AND operator in the query...I need to replace it OR operator
Another use case I am struggling with
#Entity
public class Detail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy = "detail", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Skill> skills;
}
I am trying to generate the query below using specifications
order by (select count(s.detail_id) from skill s where detail.id = s.detail_id AND s.category is not null) desc
I have used the code below
cq.orderBy(cb.desc(cb.size(details.get("skills"))));
But the query it generates is
order by (select count(s.detail_id) from skill s where detail.id = s.detail_id) desc
Notice that I am unable to add an extra AND to the order by clause

I believe you can not change that AND.
could you change the query in the following way
SELECT DISTINCT p.name
FROM partner p INNER JOIN detail d ON p.detail_id = d.id, account a
where d.account_id = a.id
OR d.crm_id = a.top_parent
OR d.crm_id = a.global_partner
and the jpa criteria similar to
Join<Partner, Detail> details = root.join("detail");
Root<Account> account = criteria.from(Account.class);
Predicate global = cb.equal(details.get("crm_id"), account.get("top_parent"));
Predicate top = cb.equal(details.get("crm_id"), account.get("global_partner"));
Predicate byId = cb.equal(details.get("account").get("id"), account.get("id"));
Predicate or = cb.or(global, top, byId);
criteria.where(or);

Related

Convert inner join native query to jpql

I have this method
#Query("select * from feed_tbl feed inner join view_tbl viewers on feed.id <> viewers.feed_id where viewers.user_id = :userId", nativeQuery = true)
fun findAll(#Param("userId") userId: Long): List<Feed>
entities:
User,
Feed
view_tbl is JoinTable in user entity
You should be able to use not in construct:
select f from Feed f where f not in (
select u.feeds from User u where u.id = :userId
)
Of cause you will need to map User to Feed as many-to-many

How to use MAX in subquery in LINQ

I am trying to write my first query in LINQ
This is my SQL query
SELECT P.id,PS.Id,P.CPersonName
,PS.StartDate FROM Provider P
LEFT OUTER JOIN ProviderSubscription PS ON
P.id=PS.providerID
AND PS.Id=(SELECT max(id)from ProviderSubscription where
providerSubscription.ProviderId=Provider.id)
And so far i wrote this LINQ.
var query = (from p in db.Providers
join ps in db.ProviderSubscriptions on p.Id
equals ps.ProviderId
select new ViewModel
{
providerid = p.Id,
providername = p.ProviderName,
subscriptiondate = ps.ExpiryDate,
}).ToList();
I am unable to add this part in my LINQ.
AND PS.Id=(SELECT max(id)from ProviderSubscription where
providerSubscription.ProviderId=Provider.id)
I don't think you need a subquery, when you're doing a join with same tables and with same conditions then there is NO need to again write an inner query with same tables. Below query should return same result:
var query = (from p in db.Providers
join ps in db.ProviderSubscriptions on p.Id equals ps.ProviderId
where ps.Contains(ps.Max(u=>u.id))
select new ViewModel
{
providerid = p.Id,
providername = p.ProviderName,
subscriptiondate = ps.ExpiryDate,
}).ToList();

CRM 2011- LINQ query joining Account, Case and Activity entity

I try to make the following query using Account, Case and Activity entities :
*var findCases =
from a in context.AccountSet
join c in context.IncidentSet
on a.AccountId equals c.CustomerId.Id
join p in context.ActivityPointerSet
on c.Id equals p.RegardingObjectId.Id
select new
{
TicketNumber = c.TicketNumber,
IncidentId = c.IncidentId,
CreatedOn = c.CreatedOn,
StateCode = c.StateCode,
AccountName = a.Name
};*
The execution of this query gives the error:
AttributeFrom and AttributeTo must be either both specified or both ommited. You can not pass only one or the other. AttributeFrom: , AttributeTo: regardingobjectid
Any suggestion will be appreciated.
Regards.
Radu Antonache
Remove CasesForAccount from the query..
*var findCases =
from a in context.AccountSet
join c in context.IncidentSet
on a.AccountId equals c.CustomerId.Id
join p in context.ActivityPointerSet
on c.Id equals p.RegardingObjectId.Id
select new
{
TicketNumber = c.TicketNumber,
IncidentId = c.IncidentId,
CreatedOn = c.CreatedOn,
StateCode = c.StateCode,
AccountName = a.Name
};*

How to select first row of each id linq

So I have few tables and i want inner join it information two create
new object. But I have a little bit trouble.
One my table have connection one to many, and when linq request , it
give me more result than i want , he just copy information. I need
request something like this:
IPagedList<HelperListings> srch = (from l in db.gp_listing
where l.DateCreated > weekago
join lp in db.gp_listing_photo on l.Id equals lp.ListingId
join loc in db.gp_location on l.LocationId equals loc.Id
orderby l.DateCreated ascending
select new HelperListings { id = l.Id, HouseNumber = l.HouseNumber,ListingPrice = l.ListingPrice, PhotoUrl = lp.PhotoUrl.First(), AreaStateCode = loc.AreaStateCode }).ToList().ToPagedList(page ?? 1, 15);
PhotoUrl = lp.PhotoUrl.First() i need something like this but i don`t have any ideas how to do it. Need ur help guys.
UPDATE :
Responding to your comment, you have at least 2 options : 1. use group by and select only the first PhotoUrl from each group, or 2. don't join to gp_listing_photo table to avoid duplicated rows, and use subquery to get only the first PhotoUrl. Example for the latter :
IPagedList<HelperListings> srch =
(from l in db.gp_listing
where l.DateCreated > weekago
join loc in db.gp_location on l.LocationId equals loc.Id
orderby l.DateCreated ascending
select new HelperListings
{
id = l.Id,
HouseNumber = l.HouseNumber,
ListingPrice = l.ListingPrice,
PhotoUrl = (from lp in db.gp_listing_photo where l.Id = lp.ListingId select lp.PhotoUrl).FirstOrDefault(),
AreaStateCode = loc.AreaStateCode
}
).ToList().ToPagedList(page ?? 1, 15);
How about simply appending .Distinct() after your LINQ query to avoid duplicated data :
IPagedList<HelperListings> srch =
(from l in db.gp_listing
where l.DateCreated > weekago
join lp in db.gp_listing_photo on l.Id equals lp.ListingId
join loc in db.gp_location on l.LocationId equals loc.Id
orderby l.DateCreated ascending
select new HelperListings
{
id = l.Id,
HouseNumber = l.HouseNumber,
ListingPrice = l.ListingPrice,
PhotoUrl = lp.PhotoUrl,
AreaStateCode = loc.AreaStateCode
}
).Distinct().ToList().ToPagedList(page ?? 1, 15);
For Reference : LINQ Select Distinct with Anonymous Types

Sql Query in Linq

i need to write sql query in string and pass it to linq like executenonquery() in ado.net
but i need to return data from 4 tables
Example Query :
SELECT *
FROM dbo.GeneralAd INNER JOIN
dbo.Category ON dbo.GeneralAd.FkCategoryID = dbo.Category.CategoryID INNER JOIN
dbo.District ON dbo.GeneralAd.FkDistrictID = dbo.District.DistrictID LEFT OUTER JOIN
dbo.Users ON dbo.GeneralAd.FkApprovedByID = dbo.Users.UserID AND dbo.GeneralAd.FKAddedByID = dbo.Users.UserID where .........
how to return data from 4 tables with executenonquery method in linq ?
I'm not sure why you why you want to return all columns from all tables. That seems unnecessary. You can get to the District and Category fields from the GeneralAd object.
What I would probably do is define a property on the General Ad object that executes a select to get the associated User.
If you did want to do it in Linq, you could use something like this:
var results = (from ga in DataContext.GeneralAds
select new
{
Col1 = ga.Col1,
Col2 = ga.Category.Col2,
Col3 = ga.District.Col3,
Col4 = (from u in DataContext.Users
where u.UserID = ga.FkApprovedByID AND u.UserID = ga.FKAddedByID
select u.Col4)
});
You might have to add an Any() method on Col4:
var results = (from ga in DataContext.GeneralAds
select new
{
Col1 = ga.Col1,
Col2 = ga.Category.Col2,
Col3 = ga.District.Col3,
Col4 = ((from u in DataContext.Users
where u.UserID = ga.FkApprovedByID AND u.UserID = ga.FKAddedByID
select u.Col4).Any() ?
(from u in DataContext.Users
where u.UserID = ga.FkApprovedByID AND u.UserID = ga.FKAddedByID
select u.Col4).First() : -1)
});

Resources