I am working with some SQL that has been provided and I am running into an issue where the count in the LINQ is different from the count in the SQL and would appreciate some help if possible.
The original SQL that was given is pretty poorly arranged and has a large number of nested queries. This being one of them. I have broken the query down into its main component and am now stitching it back together with LINQ.
The SQL that I am working with is here :
DECLARE #QSCollectionId UNIQUEIDENTIFIER = 'f52ec043-b360-4266-f95f-08d7c66074pe';
SELECT fieldid
Count(fieldid) AS fieldcount,
Sum(CASE
WHEN answer = [value] AND Answer IS NOT NULL THEN 1
ELSE 0
END) AS FieldAnswerMatchCount
FROM (SELECT DISTINCT FCI.fieldid,
answer,
QSA.qsrid,
FAG.fieldid AS dependentfield,
FAG.value
FROM forms.fieldconstraints FCI
INNER JOIN forms.sectionfieldmappings SFM
ON FCI.fieldid = SFM.fieldid
INNER JOIN forms.qssectionmappings QSSM
ON SFM.sectionid = QSSM.sectionid
INNER JOIN sessions.qsr
ON QSSM.qsid = qsr.qsid
--AND Qsr.QSCollectionId=#QSCollectionId
LEFT JOIN forms.answerguides FAG
ON
FCI.dependantanswerguideid = FAG.answerguideid
LEFT JOIN sessions.qsranswers QSA
ON FAG.fieldid = QSA.fieldid
AND Qsr.QsrId = QSA.qsrid
) AS
FieldConstr
GROUP BY fieldid
The LINQ
var id = Guid.Parse("f52ec043-b360-4266-f95f-08d7c66074be");
var firstResultPartThree = (from fci in FieldConstraints
join sfm in SectionFieldMappings on fci.FieldId equals sfm.FieldId
join qssm in QSSectionMappings on sfm.SectionId equals qssm.SectionId
join qsr in QSRs on new { qssm.QSId } equals new { qsr.QSId }
join ag in AnswerGuides on fci.DependantAnswerGuideId equals ag.AnswerGuideId into agResult
from agJoin in agResult.DefaultIfEmpty()
join qsrAnswers in QSRAnswers on new { agJoin.FieldId, qsr.QsrId } equals new {qsrAnswers.FieldId, qsrAnswers.QsrId} into qsrAnswersResult
from qsrAnswersJoin in qsrAnswersResult.DefaultIfEmpty()
//where qsr.QSCollectionId == id
select new {
FieldId = fci.FieldId,
Answer = qsrAnswersJoin.Answer,
QsrId = (Guid?)qsrAnswersJoin.QsrId,
DependentFieldId = agJoin.FieldId,
Value = agJoin.Value
}
);
firstResultPartThree.Dump();
var firstResultPartTwo = (from fr in firstResultPartThree
where fr.FieldId == Guid.Parse("98CA6B6F-4070-4CEB-E9F1-08D7C66278F9")
group fr by fr.FieldId into grp
select new {
FieldId = grp.Key,
Fieldcount = grp.Count(),
FieldAnswerMatchCount = grp.Count(x => (Guid?)grp.Key.Value != null)
}
);
The result of the LINQ in the example below gives me
FieldId | fieldcount | FieldAnswerMatchCount
98ca6b6f-4070-4ceb-e9f1-08d7c66278f9 | 4 | 4 |
The result of the sql for the same data is
98ca6b6f-4070-4ceb-e9f1-08d7c66278f9 | 3 | 2 |
The area that I am struggling with is
select new {
FieldId = grp.Key,
Fieldcount = grp.Count(),
FieldAnswerMatchCount = grp.Count(x => (Guid?)grp.Key.Value != null)
I understand that the count in the select is wrong, however I do not know how I need to correct it and would be grateful for some help.
Related
I'm using Linq (code-first approach) query to retrieve the data from DB and couldn't able to get similar result while using below linq query:
from msi in db.MainSaleInvoiceTbls
join dsi in db.DetialSaleInvoiceTbls on msi.Id equals dsi.MainSaleInvoiceId
join ca in db.CustomerAccounts on msi.CustomerId equals ca.Id
join cg in db.MiscLists on ca.CustomerGroupId equals cg.Id
where msi.IsActive == true && msi.CompanyId == UniversalInfo.UserCompany.Id && msi.MainSaleInvoiceDataType == MainSaleInvoiceType.SOInvoice
group msi by new { dsi,msi.Date,msi.FinancialVoucher,msi.SaleOrderPrefix,msi.SaleOrderNumber,msi.SalesId,ca.CustomerName,ca.AccountCode,cg.Name }
into mainSaleInvoice
from dx in mainSaleInvoice.DefaultIfEmpty()
// orderby main.Id
select new
{
Date = mainSaleInvoice.Key.Date,
Voucher = mainSaleInvoice.Key.FinancialVoucher,
InvoiceAccount = mainSaleInvoice.Key.AccountCode,
CustomerName = mainSaleInvoice.Key.CustomerName,
CustomerGroup = mainSaleInvoice.Key.Name,
Invoice = mainSaleInvoice.Key.SaleOrderPrefix + mainSaleInvoice.Key.SaleOrderNumber,
PurchaseOrder = mainSaleInvoice.Key.SalesId,
SalesTax = "",
InvoiceAmount = mainSaleInvoice.Sum(x => (Double)(mainSaleInvoice.Key.Quantity * mainSaleInvoice.Key.UnitPrice))
}).ToList()
In linq, i need to get shortdatetimeString() and sum() of (unitprice* quantity) from child table DetialSaleInvoiceTbls
being new in query writing, I don't know where and what I'm doing wrong. Any suggestions would be much appreciated.
var list=from msi in db.MainSaleInvoiceTbls
join dsi in db.DetialSaleInvoiceTbls on msi.Id equals dsi.MainSaleInvoiceId
join ca in db.CustomerAccounts on msi.CustomerId equals ca.Id
join cg in db.MiscLists on ca.CustomerGroupId equals cg.Id into a
where msi.IsActive == true && msi.CompanyId == UniversalInfo.UserCompany.Id
&& msi.MainSaleInvoiceDataType == MainSaleInvoiceType.SOInvoice
from cg in a.DefaultIfEmpty()
select new
{mainSaleInvoice.Date,
mainSaleInvoice.FinancialVoucher,mainSaleInvoice.AccountCode,
mainSaleInvoice.CustomerName,mainSaleInvoice.Name,
mainSaleInvoice.SaleOrderPrefix, mainSaleInvoice.SaleOrderNumber,
mainSaleInvoice.SalesId, }).sum(x=>x. (mainSaleInvoice.Quantity *
mainSaleInvoice.UnitPrice)).groupby msi new
{msi.Date,msi.FinancialVoucher,msi.SaleOrderPrefix,msi.SaleOrderNumber,
msi.SalesId};
Date = mainSaleInvoice.Date;
Voucher = mainSaleInvoice.FinancialVoucher;
InvoiceAccount = mainSaleInvoice.AccountCode;
CustomerName = mainSaleInvoice.CustomerName;
CustomerGroup = mainSaleInvoice.Name;
Invoice = mainSaleInvoice.SaleOrderPrefix +
mainSaleInvoice.SaleOrderNumber;
PurchaseOrder = mainSaleInvoice.SalesId;
SalesTax = "";
InvoiceAmount =list;
I'm trying to rewrite sql query to linq but can't do it myself.
The most problem for me is to get I,II and III aggregated values.
Sql query:
select o.Name,t.TypeID, SUM(e.I),SUM(e.II),SUM(e.III) from Expenditure e
join Finance f on f.FinanceId = e.FinanceId
join FinanceYear fy on fy.FinanceYearId = f.FinanceYearId and fy.StatusId = 1
join Project p on p.ProjectId = fy.ProjectId
join Organization o on o.OrganizationId = p.OrganizationId
join Type t on t.TypeID = p.TypeID
where fy.Year = 2018
group by o.Name,s.TypeID
and what I have done so far is:
var x = (from e in _db.Expenditures
join f in _db.Finances on e.FinanceId equals f.FinanceId
join fy in _db.FinanceYears on f.FinanceYearId equals fy.FinanceYearId and fy.StatusId = 1 // this does not work, cant join on multiple conditions?
join p in _db.Projects on fy.ProjectId equals p.ProjectId
join o in _db.Organizations on p.OrganizationId equals o.OrganizationId
join s in _db.Types on p.TypeId equals s.TypeId
group new { o, s } by new { o.OrganizationId, s.TypeId }
into grp
select new AggModel
{
OrganizationId = grp.Key.OrganizationId,
TypeId = grp.Key.TypeId,
I = ?,
II = ?,
III = ?,
}
);
Try something like this:
group new { e, o, s } by new { o.OrganizationId, s.TypeId }
into grp
select new AggModel
{
OrganizationId = grp.Key.OrganizationId,
TypeId = grp.Key.TypeId,
I = grp.Sum(a => a.e.I),
II = grp.Sum(a => a.e.II),
III = grp.Sum(a => a.e.III),
}
You'll need to adjust the right side of the lambda to navigate to the correct property.
You Need to use the Group by for aggregation methods.
Check the below link for more Knowledge.
How to use aggregate functions in linq with joins?
This is my query:
var results = from table1 in dtSplitDates.AsEnumerable()
join table2 in dtSplitDates.AsEnumerable() on (int)table1["FID"] equals (int)table2["FID"] into lj
from r in lj.DefaultIfEmpty()
select dtSplitDates2.LoadDataRow(new object[]
{
r["FID"],
r["SLNO"],
r == null ? string.Empty : r["Dates"]
}, false);
Currently i am joining on Column FID - due to which i am getting 36 records (duplicates):
However in order to avoid duplicates i need to join also on SLNO column but i am unable to write that query - please help.
As per my understanding you want two join condition; Try this
var results = from table1 in dtSplitDates.AsEnumerable()
join table2 in dtSplitDates.AsEnumerable()
on new {id1 =(int)table1["FID"], SLno1= (int)table1["SLNO"]}
equals new {id2=(int)table2["FID"], SLno2=(int)table2["SLNO"]} into lj
from r in lj.DefaultIfEmpty()
select dtSplitDates2.LoadDataRow(new object[]
{
r["FID"],
r["SLNO"],
r == null ? string.Empty : r["Dates"]
}, false);
Try to implement with this example:
For Multiple Joins:
var result=(from com in db.Company.AsEnumerable()
join c in db.Country.AsEnumerable() on com.CountryID equals c.CountryID
join s in db.State.AsEnumerable() on com.StateID equals s.StateID
join ct in db.City.AsEnumerable() on com.CityID equals ct.CityID
orderby com.Name
select new CompanyModel()
{
CompanyID = com.CompanyID,
Name = com.Name,
AddressLine1 = com.AddressLine1,
CountryID = com.CountryID,
StateID = com.StateID,
CityID = com.CityID,
Country = c.CountryID,
State = s.StateID,
City = ct.CityID,
Pin = com.Pin,
Phone = com.Phone,
}).Distinct().ToList();
public static IEnumerable<AppCache> GetTopRatedApps(string language,bool isinitialized)
{
List<AppCache> objApps = new List<AppCache>();
objApps = GetAllApps(isinitialized,language).ToList();
List<RatingCache> objRatings = new List<RatingCache>();
objRatings = GetAllRatings();
var query =
from Apps in objApps
join ratings in objRatings
on Apps.AppId equals ratings.AppId where ratings.RatingGiven == 1
select new AppCache();
return query;
}
Stored Procedure:
select o.AppId, count(*) as ItemCount
from App o
inner join Rating od
on o.AppId = od.AppId
where od.RatingGiven = 1
group by o.AppId
Can't figure out how to get the item count from the list.
Not: AppCache is equivalent to App
This should be the translation of your stored procedure. If you want to return something else, just modify the select method.
var query = from Apps in objApps
join ratings in objRatings
on Apps.AppId equals ratings.AppId
where ratings.RatingGiven == 1
group Apps by Apps.AppId into g
select new { AppId = g.AppId, ItemCount = g.Count() }
I have a search that looks for two things. Items and Contacts. They each have their own table with their own unique attributes. I am able to successfully search each independent of eachother and return the results to two list views. But is it ugly and paging has become a issue so I have to convert these two tables into a like result that I can display as a search result. These results have no relationship directly with eachother.
The group t3 by new is throwing me off. Do I have to group them to have it become a like result? The results currently get displayed in a ListView using for example <%#Eval("ItemName") %>
ItemContext db = new ItemContext(); //DB connection (Item,Contact)
var q = (from t1 in db.Item
join t2 in db.Categories on t1.CategoryID equals t2.CategoryID
join t7 in db.Divisions on t1.DivisionID equals t7.DivisionID
from t3 in db.Contacts
join t4 in db.Categories on t3.CategoryID equals t4.CategoryID
join t5 in db.Divisions on t3.DivisionID equals t5.DivisionID
join t6 in db.ContactTitle on t3.ContactTitlesID equals t6.ContactTitlesID
where
(DDLInt == 1 || t3.DivisionID == DDLInt) &&
//Contains
(
t3.ContactName.Contains(keyword) ||
t3.ContactEmail.Contains(keyword) ||
t3.ContactOPhone.Contains(keyword) ||
t3.ContactID.Equals(searchID)
)
group t3 by new
{
t3.ContactID,
t3.ContactName,
t3.ContactOPhone,
t3.ContactCell,
t3.ContactEmail,
t3.DivisionID,
t3.CategoryID,
t4.CategoryName,
t5.DivisionName,
t6.ContactTitlesName
}
into i
select new
{
i.Key.ContactID,
i.Key.ContactName,
i.Key.ContactOPhone,
i.Key.ContactEmail,
i.Key.ContactCell,
i.Key.CategoryName,
i.Key.DivisionName,
i.Key.CategoryID,
i.Key.DivisionID,
i.Key.ContactTitlesName
});
return q.ToList<dynamic>();
}
Use Union():
var contacts = from c in db.Contacts
select new {
Id = c.ContactID,
Name = c.ContactName,
Phone = c.ContactOPhone,
...
CategoryName = c.Category.CategoryName,
DivisionName = c.Division.DivisionName,
ContactTitlesName = c.ContactTitle.ContactTitlesName
}
var items = from t1 in db.Item
select new {
Id = t1.ItemID,
Name = t1.ItemName,
Phone = t1.??, // string.Empty?
... // more properties corresponding
// with the ones above
CategoryName = t1.Category.CategoryName,
DivisionName = t1.Division.DivisionName,
ContactTitlesName = string.Empty
}
var all = contacts.Union(items);