I have a SQL Query which I want to convert in Linq or want to show data
as pictured here
Here is the query:
select sae_subcategorymaster.subject, count(sae_tblbookdetail.title)
from sae_tblbookdetail inner join sae_subcategorymaster
on sae_subcategorymaster.subject=sae_tblbookdetail.subject
group by sae_subcategorymaster.subject
What is a simple way to do this?
Grouping is supported in LinqEF. Provided you have your entities related. (Books have a reference to their subcategory.)
var totals = context.Books
.GroupBy(book => book.SubCategory.Subject)
.Select(group => new
{
Subject = group.Key,
BookCount = group.Count()
}).ToList();
Related
i want to ask about sql in postgresql, i got data from join with 3 table, i got the result but i got multiple data like this image
result
and here my sql code in postgresql
select users.* from users inner join model_has_roles on model_has_roles.model_id = users.id
left join roles on roles.id = model_has_roles.role_id where roles.name not in ('job-seeker') order by users.name asc
how to fix this query where i got the multiple data only 1 data to show.
and i want this sql to implement to laravel query and here my code now
public function getAccountList(){
$req = app(Request::class);
// $getAccount = User::query();
$getAccount = User::join('model_has_roles', function($join) {
$join->on('users.id', '=', 'model_has_roles.model_id');
})->leftJoin('roles', function($join){
$join->on('model_has_roles.role_id', '=', 'roles.id');
});
$getAccount->whereNotIn('roles.name', ['job-seeker']);
if ($q = $req->query('q')) {
$searchTerm = trim(strtolower($q));
$getAccount->whereRaw(
'LOWER(users.name) like (?) or LOWER(users.email) like (?)',
["%{$searchTerm}%", "%{$searchTerm}%"]
);
}
// $getAccount->get()->unique('name');
$getAccount->select(['users.*']);
$paginator = $this->pagination($getAccount);
return $this->paginate($paginator, new UserTransformer);
}
how to fix the query only 1 data to show not the multiple same data. thank you for helping me. God Bless You
use distinct()
$data = DB::table('test')->[your query builder]->distinct()->get();
Laravel Query Builder Docs
Just change a bit to make it related to your query builder
I have following SQL Query:
SELECT campaigns.* , campaign_countries.points, offers.image
FROM campaigns
JOIN campaign_countries ON campaigns.id = campaign_countries.campaign_id
JOIN countries ON campaign_countries.country_id = countries.id
JOIN offers ON campaigns.offer_id = offers.id
WHERE countries.code = 'US'
This works perfectly well. I want its rails active record version some thing like:
Campaign.includes(campaign_countries: :country).where(countries: {code: "US"})
Above code runs more or less correct query (did not try to include offers table), issue is returned result is collection of Campaign objects so obviously it does not include Points
My tables are:
campaigns --HAS_MANY--< campaign_countries --BELONGS_TO--< countries
campaigns --BELONGS_TO--> offers
Any suggestions to write AR version of this SQL? I don't want to use SQL statement in my code.
I some how got this working without SQL but surely its poor man's solution:
in my controller I have:
campaigns = Campaign.includes(campaign_countries: :country).where(countries: {code: country.to_s})
render :json => campaigns.to_json(:country => country)
in campaign model:
def points_for_country country
CampaignCountry.joins(:campaign, :country).where(countries: {code: country}, campaigns: {id: self.id}).first
end
def as_json options={}
json = {
id: id,
cid: cid,
name: name,
offer: offer,
points_details: options[:country] ? points_for_country(options[:country]) : ""
}
end
and in campaign_countries model:
def as_json options={}
json = {
face_value: face_value,
actual_value: actual_value,
points: points
}
end
Why this is not good solution? because it invokes too many queries:
1. It invokes query when first join is performed to get list of campaigns specific to country
2. For each campaign found in first query it will invoke one more query on campaign_countries table to get Points for that campaign and country.
This is bad, Bad and BAD solution. Any suggestions to improve this?
If You have campaign, You can use campaign.campaign_countries to get associated campaign_countries and just get points from them.
> campaign.campaign_countries.map(&:points)
=> [1,2,3,4,5]
Similarly You will be able to get image from offers relation.
EDIT:
Ok, I guess now I know what's going on. You can use joins with select to get object with attached fields from join tables.
cs = Campaign.joins(campaign_countries: :country).joins(:offers).select('campaigns.*, campaign_countries.points, offers.image').where(countries: {code: "US"})
You can than reference additional fields by their name on Campaign object
cs.first.points
cs.first.image
But be sure, that additional column names do not overlap with some primary table fields or object methods.
EDIT 2:
After some more research I came to conclusion that my first version was actually correct for this case. I will use my own console as example.
> u = User.includes(:orders => :cart).where(:carts => { :id => [5168, 5167] }).first
> u.orders.length # no query is performed
=> 2
> u.orders.count # count query is performed
=> 5
So when You use includes with condition on country, in campaign_countries are stored only campaign_countries that fulfill Your condition.
Try this:
Campaign.joins( [{ :campaign_countries => :countries}, :offers]).where('`countries`.`code` = ?', "US")
I am simply trying to write a query that will look like this and be eager loaded:
Select * from Users where Id IN (1,2,3)
Select * from Bids where UserId in (1,2,3)
Right now it's causing problems because the join is returning too many results.
Try using multicriteria (or Future as in this example), should issue 2 queries in 1 batch and give you the eager loading:
var bids = Session.QueryOver<Bid>()
.JoinQueryOver(b => b.User)
.WhereRestrictionOn(u => u.Id).IsIn(ids)
.Future<Bid>();
var users = Session.QueryOver<User>()
.WhereRestrictionOn(u => u.Id).IsIn(ids)
.List<User>();
The only problem is it will join Bid -> User, to avoid that you could use HQL:
var bids = Session.CreateQuery("from Bid b where b.User.id in (:userIds)")
.SetParameterList("userIds", ids)
.Future<Bid>();
var users = Session.QueryOver<User>()
.WhereRestrictionOn(u => u.Id).IsIn(ids)
.List<User>();
Imagine the following (simplified) database layout:
We have many "holiday" records that relate to going to a particular Accommodation on a certain date etc.
I would like to pull from the database the "best" holiday going to each accommodation (i.e. lowest price), given a set of search criteria (e.g. duration, departure airport etc).
There will be multiple records with the same price, so then we need to choose by offer saving (descending), then by departure date ascending.
I can write SQL to do this that looks like this (I'm not saying this is necessarily the most optimal way):
SELECT *
FROM Holiday h1 INNER JOIN (
SELECT h2.HolidayID,
h2.AccommodationID,
ROW_NUMBER() OVER (
PARTITION BY h2.AccommodationID
ORDER BY OfferSaving DESC
) AS RowNum
FROM Holiday h2 INNER JOIN (
SELECT AccommodationID,
MIN(price) as MinPrice
FROM Holiday
WHERE TradeNameID = 58001
/*** Other Criteria Here ***/
GROUP BY AccommodationID
) mp
ON mp.AccommodationID = h2.AccommodationID
AND mp.MinPrice = h2.price
WHERE TradeNameID = 58001
/*** Other Criteria Here ***/
) x on h1.HolidayID = x.HolidayID and x.RowNum = 1
As you can see, this uses a subquery within another subquery.
However, for several reasons my preference would be to achieve this same result in NHibernate.
Ideally, this would be done with QueryOver - the reason being that I build up the search criteria dynamically and this is much easier with QueryOver's fluent interface. (I had started out hoping to use NHibernate Linq, but unfortunately it's not mature enough).
After a lot of effort (being a relative newbie to NHibernate) I was able to re-create the very inner query that fetches all accommodations and their min price.
public IEnumerable<HolidaySearchDataDto> CriteriaFindAccommodationFromPricesForOffers(IEnumerable<IHolidayFilter<PackageHoliday>> filters, int skip, int take, out bool hasMore)
{
IQueryOver<PackageHoliday, PackageHoliday> queryable = NHibernateSession.CurrentFor(NHibernateSession.DefaultFactoryKey).QueryOver<PackageHoliday>();
queryable = queryable.Where(h => h.TradeNameId == website.TradeNameID);
var accommodation = Null<Accommodation>();
var accommodationUnit = Null<AccommodationUnit>();
var dto = Null<HolidaySearchDataDto>();
// Apply search criteria
foreach (var filter in filters)
queryable = filter.ApplyFilter(queryable, accommodationUnit, accommodation);
var query1 = queryable
.JoinQueryOver(h => h.AccommodationUnit, () => accommodationUnit)
.JoinQueryOver(h => h.Accommodation, () => accommodation)
.SelectList(hols => hols
.SelectGroup(() => accommodation.Id).WithAlias(() => dto.AccommodationId)
.SelectMin(h => h.Price).WithAlias(() => dto.Price)
);
var list = query1.OrderByAlias(() => dto.Price).Asc
.Skip(skip).Take(take+1)
.Cacheable().CacheMode(CacheMode.Normal).List<object[]>();
// Cacheing doesn't work this way...
/*.TransformUsing(Transformers.AliasToBean<HolidaySearchDataDto>())
.Cacheable().CacheMode(CacheMode.Normal).List<HolidaySearchDataDto>();*/
hasMore = list.Count() == take;
var dtos = list.Take(take).Select(h => new HolidaySearchDataDto
{
AccommodationId = (string)h[0],
Price = (decimal)h[1],
});
return dtos;
}
So my question is...
Any ideas on how to achieve what I want using QueryOver, or if necessary Criteria API?
I'd prefer not to use HQL but if it is necessary than I'm willing to see how it can be done with that too (it makes it harder (or more messy) to build up the search criteria though).
If this just isn't doable using NHibernate, then I could use a SQL query. In which case, my question is can the SQL be improved/optimised?
I have manage to achieve such dynamic search criterion by using Criteria API's. Problem I ran into was duplicates with inner and outer joins and especially related to sorting and pagination, and I had to resort to using 2 queries, 1st query for restriction and using the result of 1st query as 'in' clause in 2nd creteria.
my code is:
List<Benutzer> users = (from a in dc.Benutzer
select a).ToList();
I need this code but I only want to select 3 of the 20 Columns in the "Benutzer"-Table.
What is the syntax for that?
Here's a query expression:
var users = (from a in dc.Benutzer
select new { a.Name, a.Age, a.Occupation }).ToList();
Or in dot notation:
var users = dc.Benutzer.Select(a => new { a.Name, a.Age, a.Occupation })
.ToList();
Note that this returns a list of an anonymous type rather than instances of Benutzer. Personally I prefer this approach over creating a list of partially populated instances, as then anyone dealing with the partial instances needs to check whether they came from to find out what will really be there.
EDIT: If you really want to build instances of Benutzer, and LINQ isn't letting you do so in a query (I'm not sure why) you could always do:
List<Benutzer> users = dc.Benutzer
.Select(a => new { a.Name, a.Age, a.Occupation })
.AsEnumerable() // Forces the rest of the query to execute locally
.Select(x => new Benutzer { Name = x.Name, Age = x.Age,
Occupation = x.Occupation })
.ToList();
i.e. use the anonymous type just as a DTO. Note that the returned Benutzer objects won't be associated with a context though.
List<Benutzer> users = (from a in dc.Benutzer
select new Benutzer{
myCol= a.myCol,
myCol2 = a.myCol2
}).ToList();
I think that's what you want if you want to make the same kind of list. But that assumes that the properties you are setting have public setters.
try:
var list = (from a in dc.Benutzer select new {a.Col1, a.Col2, a.Col3}).ToList();
but now you have list of anonymous object not of Benutzer objects.