Linq to sql - nested select with groupby - linq

I have the following SQL query:
SELECT * FROM [dbo].[Bil_Audit_BillingParameter] WHERE ([Status4Eyes]!='APPROVED' OR [Status4Eyes] IS NULL )AND
[LastComment] != '' AND
(Service='EUR' OR Service='S1') AND
[AudId] IN (SELECT MAX([AudId])
FROM [Bil_Audit_BillingParameter]
GROUP BY ID) UNION SELECT * FROM
[dbo].Bil_Audit_BillingParameter] WHERE ([Status4Eyes]!='APPROVED' OR [Status4Eyes] IS NULL) AND
[LastComment] != '' AND
(Service='EUR' OR Service='S1') AND
[AudId] IN (SELECT MIN([AudId])
FROM [Bil_Audit_BillingParameter]
GROUP BY ID)
How it is converting to linq? I tried the following , but ends up with error.
public IQueryable<ParameterUpdates> Get(ODataQueryOptions op)
{
var audIdMax = db.ParameterUpdates.GroupBy(x => x.ID).Select(v => v.Max(x => x.AudId));
var audIdMin = db.ParameterUpdates.GroupBy(x => x.ID).Select(a => a.Min(x => x.AudId));
var results1 = db.ParameterUpdates.Where(p => (!p.Status4Eyes.Contains("Approved") || string.IsNullOrEmpty(p.Status4Eyes)) &&
!p.LastComment.Contains("NULL") &&
(p.Service.Contains("EUR") || p.Service.Contains("S1")) &&
p.AudId.Equals(audIdMax));
var results2 = db.ParameterUpdates.Where(p => (!p.Status4Eyes.Contains("Approved") || string.IsNullOrEmpty(p.Status4Eyes)) &&
!p.LastComment.Contains("NULL") &&
(p.Service.Contains("EUR") || p.Service.Contains("S1")) &&
p.AudId.Equals(audIdMin));
var results = results1.Union(results2);
return results.AsQueryable();
}
Could anyone please help.

You can try this, first group by id create the filter output. Then inner join the filter with max or min audit id with the actual table and find the result.
var filter = ParameterUpdate.Where(p => (p.status == "Approved" || p.status == null)
&& p.lastComment != ""
&&(p.service=="EUR" || p.service=="S1")).GroupBy(p => p.id);
var result = (from p in ParameterUpdate
from f in filter
where p.auditId == f.Min(m => m.auditId) ||
p.auditId == f.Max(m => m.auditId)
select p);

public IQueryable<ParameterUpdates> Get()
{
var groupMax = db.ParameterUpdates
.GroupBy(u => u.ID)
.Select(grp => grp.Max(x => x.AudId));
var groupMin = db.ParameterUpdates
.GroupBy(u => u.ID)
.Select(grp => grp.Min(x => x.AudId));
var results = (db.ParameterUpdates.
Where(r => (r.Status4Eyes != "APPROVED" || r.Status4Eyes == null) &&
(r.LastComment != null) &&
(r.Service == "EUR" || r.Service == "S1") &&
(groupMax.Contains(r.AudId) || groupMin.Contains(r.AudId))
)).ToList();
return results.AsQueryable();

Related

Linq to Entities - Correlated Subquery

I have the following query:
var query = db.DepoAccounts
.Join(db.DepoAccountDetails,
t1 => new { t1.INTEG_REF_NO, t1.BASE_DATE },
t2 => new { t2.INTEG_REF_NO, t2.BASE_DATE },
(t1, t2) => new DataCustomerAccountGDWHModel
{
BranchNumber = t1.BR_NO,
BookedBalance = t2.DP_FACE_BAL_VAL_ADJ,
}
)).Where(ac => ac.BranchNumber == "500" &&
(ac.AccountNumber.Substring(0, 1) == "H" ||
ac.AccountNumber.Substring(0, 1) == "F"));
How do I add to the above to do a correlated subquery?
AND DEP2.EFECT_DT = (SELECT MAX(DEP3.EFECT_DT) FROM
R_DBLNK_US.DW_TRN_DEPO_ACC_DTL_D DEP3
WHERE DEP.INTEG_REF_NO = DEP3.INTEG_REF_NO
AND DEP.BASE_DATE = DEP3.BASE_DATE)

Dynamic Bool Query for NEST (ElasticSearch)

Good day:
I'm trying to achieve a dynamic Bool Query. Example...
QueryContainer addressQuery = null;
QueryContainer typeQuery = null;
BoolQueryDescriptor <Facility> boolQuery = new BoolQueryDescriptor<Facility>();
QueryContainerDescriptor<Facility> sh = new QueryContainerDescriptor<Facility>();
SearchDescriptor<Facility> mainSh = new SearchDescriptor<Facility>();
if (search.searchTerm != null)
{
addressQuery = sh.Term(f => f.Address, search.searchTerm) ||
sh.Match(m => m.Field(f => f.Address).Query(search.searchTerm) ) ||
sh.Term(f => f.ZipCode, search.searchTerm) ||
sh.Match(m => m.Field(f => f.State).Query(search.searchTerm));
boolQuery = boolQuery.Should(b => addressQuery);
}
if (search.type != null) {
typeQuery = sh.Term(f => f.Types.First(), search.type);
boolQuery = boolQuery.Must(b => typeQuery && addressQuery);
}
if (boolQuery != null)
{
mainSh = mainSh.Query(q => q.Bool(b => boolQuery));
request = await this._elasticClient.SearchAsync<Facility>(s => mainSh.Size(search.size));
}
This query is turning into a OR between AddressQuery and TypeQuery however, I'd like to achieve an And condition between both query. Effectively making the query dynamic. Is this possible? Example: dynamic addressQuery && typeQuery.
Thanks.
Fire it out..you can && or || query containers...sorter like:
queryContainer1=queryContainer1 && queryContainer2
Then .bool(b => b(queryContainer1)).

Linq Join queries

Can someone refactor my code in a simpliest way?
var yearly = context.Prospects.Join(context.Prospect_Details, prospect => prospect.ProspectId,
prosDetail => prosDetail.ProspectID,
(prospect, prosDetail) => new {Prospect = prospect, ProspectDetail = prosDetail})
.Join(context.Sources, prospect => prospect.Prospect.SourceId, source => source.SourceId, (prospect, source) => new {Prospect = prospect, Source = source})
.Where(
c =>
c.Prospect.Prospect.Customer.StoreId == storeid && c.Prospect.ProspectDetail.IsDeleted == false
&& c.Prospect.ProspectDetail.DateCreated.Year == date.Year && c.Prospect.Prospect.Customer.IsMerge == null
&& c.Prospect.Prospect.SubStatus.Status.Name == "Sold").ToList();
var daily = context.Prospects.Join(context.Prospect_Details, prospect => prospect.ProspectId,
prosDetail => prosDetail.ProspectID,
(prospect, prosDetail) => new { Prospect = prospect, ProspectDetail = prosDetail })
.Join(context.Sources, prospect => prospect.Prospect.SourceId, source => source.SourceId, (prospect, source) => new { Prospect = prospect, Source = source })
.Where(
c =>
c.Prospect.Prospect.Customer.StoreId == storeid && c.Prospect.ProspectDetail.IsDeleted == false
&& c.Prospect.ProspectDetail.DateCreated.Year == date.Year && c.Prospect.ProspectDetail.DateCreated.Month == date.Month
&& c.Prospect.ProspectDetail.DateCreated.Day == date.Day && c.Prospect.Prospect.Customer.IsMerge == null
&& c.Prospect.Prospect.SubStatus.Status.Name == "Sold").ToList();
i need to know if there's a simplest way, im newbie in linq-sql.

Linq join and group by

I am trying to write the following PLSQL query in linq, but am coming a little unstuck on the group by:
select
sub.EmpID,
Min(sub.Stage1) Stage1,
Min(sub.Stage2) Stage2,
Min(sub.Stage3) Stage3,
Min(sub.Prob1) Prob1,
Min(sub.Prob2) Prob2
from
(select
det.det_numbera EmpID,
case when apr.apr_performa = '1'
then max(apr.apr_datec)
else null
end Stage1,
case when apr.apr_performa = '2'
then max(apr.apr_datec)
else null
end Stage2,
case when apr.apr_performa = '3'
then max(apr.apr_datec)
else null
end Stage3,
case when apr.apr_performa = '5'
then max(apr.apr_datec)
else null
end Prob1,
case when apr.apr_performa = '6'
then max(apr.apr_datec)
else null
end Prob2
from emdet det
left outer join emapr apr
on det.det_numbera = apr.det_numbera
group by det.det_numbera, apr.apr_performa) sub
group by sub.Empid
I have managed to partially do the sub query but came unstuck on the grouping before I could get the outer query working:
public List<ComplianceDetails> MyComplianceDetails(List<JobDetail> staff, List<Compliance> compliance)
{
List<ComplianceDetails> compdet =
(from s in staff
join c in compliance on s.EmpID equals c.EmpId into staffcomp
from sc in staffcomp.DefaultIfEmpty()
group s by new { s.EmpID, sc.Stage } into grp
select new ComplianceDetails(
s.EmpID,
s.Position,
s.Department,
s.Division,
s.Contract,
s.ContService,
s.Probation,
s.Sessional,
s.Teaching,
sc.Stage == "1" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "2" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "3" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "5" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "6" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null
)
).ToList();
return compdet;
}
EDIT//
Thanks for the help, you guided me very close to the solution this seems to work as expected:
public List<ComplianceDetails> MyComplianceDetails(List<JobDetail> staff, List<Compliance> compliance)
{
string[] tQuals = new string[] { "21", "22", "23", "24" };
var compdet =
(from det in staff
join apr in compliance on det.EmpID equals apr.EmpId
into JoinedList
from apr in JoinedList.DefaultIfEmpty()
group new { det, apr } by
new
{
det.EmpID,
Stage = apr == null ? "" : apr.Stage
} into GroupedList
select GroupedList.Select(u => new
{
EmpID = u.det.EmpID,
FullName = u.det.FullName,
Position = u.det.Position,
Department = u.det.Department,
Division = u.det.Division,
Contract = u.det.Contract,
ContService = u.det.ContService,
Probation = u.det.Probation,
Sessional = u.det.Sessional,
Teaching = u.det.Teaching,
Stage1 = u.apr == null ? null : (u.apr.Stage == "1" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Stage2 = u.apr == null ? null : (u.apr.Stage == "2" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Stage3 = u.apr == null ? null : (u.apr.Stage == "3" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Prob1 = u.apr == null ? null : (u.apr.Stage == "5" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Prob2 = u.apr == null ? null : (u.apr.Stage == "6" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
EduType = u.apr == null ? string.Empty : (tQuals.Contains(u.apr.Stage) ? u.apr.StageDesc : string.Empty),
EduDate = u.apr == null ? null : (tQuals.Contains(u.apr.Stage) ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null)
})
)
.SelectMany(u => u)
.GroupBy(u => u.EmpID)
.Select(u => new ComplianceDetails
(
u.Key,
u.First().FullName,
u.First().Position,
u.First().Department,
u.First().Division,
u.First().Contract,
u.First().ContService,
u.First().Probation,
u.First().Sessional,
u.First().Teaching,
u.Where(t => t.Stage1 == u.Max(T => T.Stage1)).Select(g => g.Stage1).FirstOrDefault(),
u.Where(t => t.Stage2 == u.Max(T => T.Stage2)).Select(g => g.Stage2).FirstOrDefault(),
u.Where(t => t.Stage3 == u.Max(T => T.Stage3)).Select(g => g.Stage3).FirstOrDefault(),
u.Where(t => t.Prob1 == u.Max(T => T.Prob1)).Select(g => g.Prob1).FirstOrDefault(),
u.Where(t => t.Prob2 == u.Max(T => T.Prob2)).Select(g => g.Prob2).FirstOrDefault(),
u.Where(t => t.EduDate == u.Max(T => T.EduDate)).Select(g => g.EduType).FirstOrDefault(),
u.Where(t => t.EduDate == u.Max(T => T.EduDate)).Select(g => g.EduDate).FirstOrDefault()
))
.ToList();
return compdet;
}
this is equivalent linq of your tsql, check this:
var query = (from det in emdet
join apr in emapr on det.det_numbera equals apr.det_numbera
into JoinedList
from apr in JoinedList.DefaultIfEmpty()
group new { det, apr } by
new
{
det.det_numbera,
apr_performa = apr == null ? "" : apr.apr.apr_performa
} into GroupedList
select GroupedList.Select(u => new
{
EmpID = u.det.det_numbera,
Stage1 = u.apr == null ? null : (u.apr.apr_performa == "1" ? GroupedList.Max(t => t.apr_datec) : null),
Stage2 = u.apr == null ? null : (u.apr.apr_performa == "2" ? GroupedList.Max(t => t.apr_datec) : null),
Stage3 = u.apr == null ? null : (u.apr.apr_performa == "3" ? GroupedList.Max(t => t.apr_datec) : null),
Prob1 = u.apr == null ? null : (u.apr.apr_performa == "5" ? GroupedList.Max(t => t.apr_datec) : null),
Prob2 = u.apr == null ? null : (u.apr.apr_performa == "6" ? GroupedList.Max(t => t.apr_datec) : null)
})
)
.SelectMany(u => u)
.GroupBy(u => u.EmpID)
.Select(u => new
{
EmpID = u.Key,
Stage1 = u.Where(t => t.Stage1 != null).DefaultIfEmpty().Min(t => t.Stage1),
Stage2 = u.Where(t => t.Stage2 != null).DefaultIfEmpty().Min(t => t.Stage2),
Stage3 = u.Where(t => t.Stage3 != null).DefaultIfEmpty().Min(t => t.Stage3),
Prob1 = u.Where(t => t.Prob1 != null).DefaultIfEmpty().Min(t => t.Prob1),
Prob2 = u.Where(t => t.Prob2 != null).DefaultIfEmpty().Min(t => t.Prob2)
})
.ToList();

DataTables Asp.Net MVC 4 Process

I have a project which using DataTables. Its working as ajax request. Its completing in 8-12 seconds. I need to optimize this code but i don't know how. String Process is worst part.
public JsonResult PageModel(Models.DataTable.ParamModel model, byte type)
{
DateTime startTime = DateTime.Now;
using (var db = Helper.Context())
{
var allEntries = db.MembershipVacations.Where(i => i.Type == type).ToList();
IEnumerable<DatabaseProcedure.Models.MembershipVacation> list = new List<DatabaseProcedure.Models.MembershipVacation>();
Func<DbModels.MembershipVacation, string> orderingFunction = (c =>
model.iSortCol_0 == 0 ? c.Membership.Username : "");
Func<DbModels.MembershipVacation, DateTime> dateOrderingFunction = (c =>
model.iSortCol_0 == 1 ? c.PostDate :
model.iSortCol_0 == 3 ? c.StartDate :
model.iSortCol_0 == 4 ? c.EndDate : DateTime.MaxValue);
/*Func<DbModels.MembershipVacation, string> orderingFunction = (c => model.iSortCol_0 == 1 ? c.ID.ToString() :
model.iSortCol_0 == 2 ? c.Membership.Username :
c.Description);*/
if (User.IsInRole("Admin"))
{
if (model.sSearch.IsNull())
{
if (model.sSortDir_0 == "asc")
{
list = allEntries
.OrderBy(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = allEntries.OrderBy(dateOrderingFunction);
}
}
else
{
list = allEntries
.OrderByDescending(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = allEntries.OrderByDescending(dateOrderingFunction);
}
}
list = list
.Skip(model.iDisplayStart)
.Take(model.iDisplayLength);
}
else
{
list = allEntries
.Where(i =>
i.Membership != null ? i.Membership.Username.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.Membership != null && i.Membership.Department != null ? i.Membership.Department.Name.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.StartDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)
|| i.EndDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase));
if (model.sSortDir_0 == "asc")
{
list = list
.OrderBy(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = list.OrderBy(dateOrderingFunction);
}
}
else
{
list = list
.OrderByDescending(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = list.OrderByDescending(dateOrderingFunction);
}
}
}
}
else
{
var approveList = db.MembershipVacationApproves.ToList();
if (model.sSearch.IsNull())
{
list = approveList
.Where(i => i.MembershipID == UI.Helper.User.ID || i.MembershipVacation.MembershipID == UI.Helper.User.ID)
.Select(i => i.MembershipVacation)
.Distinct()
.Where(i => i.Type == type)
.Skip(model.iDisplayStart)
.Take(model.iDisplayLength);
}
else
{
list = approveList
.Where(i => i.MembershipID == UI.Helper.User.ID || i.MembershipVacation.MembershipID == UI.Helper.User.ID)
.Select(i => i.MembershipVacation)
.Distinct()
.Where(i =>
i.Type == type && (
i.Membership != null ? i.Membership.Username.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.Membership.Department != null ? i.Membership.Department.Name.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.StartDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)
|| i.EndDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)))
.Skip(model.iDisplayStart)
.Take(model.iDisplayLength);
}
}
List<string[]> result = new List<string[]>();
foreach (var item in list)
{
var waiting = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Waiting) > 0;
var cancel = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Cancel) > 0;
var approve = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Approve) == item.MembershipVacationApproves.Count;
var edit = item.Membership.MembershipRelation != null ? item.Membership.MembershipRelation.OwnerID == UI.Helper.User.ID : false;
var canApprove = item.MembershipVacationApproves.Count(i => i.MembershipID == UI.Helper.User.ID) == 1;
StringBuilder name_link = new StringBuilder(),
durumu = new StringBuilder(),
islemler = new StringBuilder();
if (item.Membership.Staff != null)
{
name_link.Append("" + item.Membership.Username + "");
}
else
{
name_link.Append(item.Membership.Username);
}
if (!cancel)
{
if (approve)
{
if (DateTime.Now < item.StartDate)
{
durumu.Append("<small class='btn green-bg'>İstek onayladı.</small>");
}
else
{
if (DateTime.Now > item.EndDate)
{
durumu.Append("<small class='btn green'>Kişi izinden dönmüş.</small>");
}
else
{
durumu.Append("<small class='btn green'>Kişi izinde.</small>");
}
}
}
else
{
durumu.Append("<small class='btn orange'>İstek onaylanması için bekleniyor.</small>");
}
}
else
{
durumu.Append("<small class='btn red'>İstek iptal edilmiş</small>");
}
islemler.Append("<div class='btn-group'>");
islemler.Append("<a class='btn green' href='#' data-toggle='dropdown'><i class='icon-user'></i>İşlemler");
islemler.Append("<i class='icon-angle-down'></i></a>");
islemler.Append("<ul class='dropdown-menu'>");
islemler.Append("<li><a href='" + this.Url.Action("RequestDetail", "Vacation", new { id = item.ID }) + "' data-toggle='modal' data-target='#'><i class='icon-search'>");
islemler.Append("</i>İncele</a></li>");
/*if (User.IsInRole("İzin Onaylama") || edit)
{
islemler += "<li><a href='" + this.Url.Action("Request", "Vacation", new { id = item.ID }) + "'><i class='icon-search'>";
islemler += "</i>Düzenle</a></li>";
}*/
if (!(DateTime.Now > item.StartDate && approve) && canApprove)
{
islemler.Append("<li><i class='icon-ok'></i>Onayla</li>");
islemler.Append("<li><a href=" + this.Url.Action("DeclinePage", "Vacation", new { id = item.ID }) + " data-toggle='modal' data-target='#'><i class='icon-remove'></i>Onaylama</a></li>");
}
islemler.Append("</ul>");
islemler.Append("</div>");
result.Add(
new string[]
{
name_link.ToString(),
item.PostDate.ToString(),
item.Membership.Department != null ? item.Membership.Department.Name : string.Empty,
item.StartDate.ToString(),
item.EndDate.ToString(),
durumu.ToString(),
islemler.ToString()
});
}
var total = (DateTime.Now - startTime);
System.Diagnostics.Debug.WriteLine("total ms " + total.TotalMilliseconds);
return Json(new
{
sEcho = model.sEcho,
iTotalRecords = allEntries.Count(),
iTotalDisplayRecords = allEntries.Count(),
aaData = result
}, JsonRequestBehavior.AllowGet);
}
}
Worst part is last foreach process for make buttons and permissions
I would guess that you have an N+1 SQL query issue in your last foreach loop: you build list then trigger 5 SQL queries for each item in the list.
Advice to diagnose and fix:
Install MiniProfiler and enable database
profiling - then you'll be able to see which SQL queries are being
triggered by the request, and if you have any duplicate queries.
Make use of EntityFramework's Include method, to eager load related data when you're querying the items for list. This will save EF from having to issue separate duplicate queries within your foreach.

Resources