This my code and I want a output like in the picture:
SELECT `test`.custinfo.CustID, OtherDeductionName AS DeductionName, sum(OtherDeductionAmount) as DeductionAmount FROM `db_payroll`.`tbl_otherdeductions`
LEFT JOIN `db_payroll`.tbl_payroll
ON `db_payroll`.tbl_payroll.OtherDeductionsID = `db_payroll`.tbl_otherdeductions.OtherDeductionsID
LEFT JOIN `test`.tbl_testpayinternal on tbl_testpayinternal.PRID = tbl_payroll.PRID
LEFT JOIN `test`.tbl_testpay on tbl_testpay.PRID = tbl_payroll.PRID
LEFT JOIN `test`.custinfo on(CASE WHEN tbl_payroll.EmpID LIKE '%EX%' THEN `test`.custinfo.custid = `test`.tbl_testpay.custid ELSE `test`.custinfo.custid = `test`.tbl_testpayinternal.custid END)
WHERE `tbl_payroll`.`status` = 'Done' and `test`.custinfo.CustID = '00000008' and `db_payroll`.`tbl_payroll`.date_start = '2022-11-14' and `db_payroll`.`tbl_payroll`.date_end = '2022-11-28'
AND `db_payroll`.`tbl_payroll`.OtherDeductionsID <> ''
GROUP BY DeductionName
UNION
SELECT `test`.custinfo.CustID, StatutoryDeductionsName AS DeductionName, sum(StatutoryEE) as DeductionAmount FROM `test`.`tbl_statutorydeductions`
LEFT JOIN `test`.tbl_statutorydeductionstype
ON `test`.tbl_statutorydeductions.StatutoryDeductionsTypeID = `test`.tbl_statutorydeductionstype.StatutoryDeductionsTypeID
LEFT JOIN `db_payroll`.tbl_payroll
ON `db_payroll`.tbl_payroll.StatutoryDeductionsID = `test`.tbl_statutorydeductions.StatutoryDeductionsID
LEFT JOIN `test`.tbl_testpayinternal on tbl_testpayinternal.PRID = tbl_payroll.PRID
LEFT JOIN `test`.tbl_testpay on tbl_testpay.PRID = tbl_payroll.PRID
LEFT JOIN `test`.custinfo on(CASE WHEN tbl_payroll.EmpID LIKE '%EX%' THEN `test`.custinfo.custid = `test`.tbl_testpay.custid ELSE `test`.custinfo.custid = `test`.tbl_testpayinternal.custid END)
WHERE `tbl_payroll`.`status` = 'Done' and `test`.custinfo.CustID = '00000008' and `db_payroll`.`tbl_payroll`.date_start = '2022-11-14' and `db_payroll`.`tbl_payroll`.date_end = '2022-11-28'
AND `db_payroll`.`tbl_payroll`.StatutoryDeductionsID <> ''
GROUP BY DeductionName
UNION
SELECT `test`.custinfo.CustID, TypeOfLoan AS DeductionName, sum(AmortAmount) as DeductionAmount FROM `test`.`tbl_benamortloan`
LEFT JOIN `db_payroll`.tbl_payroll
ON `test`.tbl_benamortloan.IDno = `db_payroll`.tbl_payroll.EmpID AND `test`.tbl_benamortloan.CutOffID = `db_payroll`.tbl_payroll.CutOffID
LEFT JOIN `test`.tbl_testpayinternal on tbl_testpayinternal.PRID = tbl_payroll.PRID
LEFT JOIN `test`.tbl_testpay on tbl_testpay.PRID = tbl_payroll.PRID
LEFT JOIN `test`.custinfo on(CASE WHEN tbl_payroll.EmpID LIKE '%EX%' THEN `test`.custinfo.custid = `test`.tbl_testpay.custid ELSE `test`.custinfo.custid = `test`.tbl_testpayinternal.custid END)
WHERE `tbl_payroll`.`status` = 'Done' and `test`.custinfo.CustID = '00000008' and `db_payroll`.`tbl_payroll`.date_start = '2022-11-14' and `db_payroll`.`tbl_payroll`.date_end = '2022-11-28'
AND `db_payroll`.`tbl_payroll`.LoanPaymentsID <> ''
GROUP BY DeductionName
ORDER BY DeductionName
This is the output I want
Can you help me with this
Well, what I see so far is a great big UNION query which will produce three concatenated groups of data, each one containing sums. So maybe now all you need to do is something like:
SELECT SUM(DeductionAmount) FROM
(
..insert the text of your present query here..
)
Of course, this is the simplest example.
The key idea is this: "your present query" – textually included, within parentheses – is used as a subquery of a primary query that calculates the sum of all of the DeductionAmount columns now being provided by "your present query." "Your present query" is the source of the rows seen by the outer-level one, and what you finally get is "the result of the outer-level one."
(Always separately review the result of your intended subquery, to be sure that it is consistent and correct, before wrapping it into an outer-level query. "Query bugs" can be hard to diagnose otherwise.)
Related
Ok, I have such SQL code:
DECLARE #documentId INT = 8
SELECT
i.[status] AS [status],
i.[barcode] AS [barcode],
i.[containerId] AS [containerTypeId],
(
SUM(ISNULL(lp.[Weight], 0) * il.[factCount]) +
ISNULL(lpt.[Weight], 0)
) AS [weight],
i.[comment] AS [comment]
FROM [Items] AS i WITH(NOLOCK)
LEFT JOIN [dbo].[ItemsLines] AS il WITH(NOLOCK) ON i.[id] = il.[itemsId]
LEFT JOIN [dbo].[LagerOptions] AS lp WITH(NOLOCK) ON lp.[lagerId] = il.[lagerId]
LEFT JOIN [dbo].[LagerOptions] AS lpt WITH(NOLOCK) ON lpt.[lagerId] = i.[containerId]
WHERE #documentId = i.[documentId]
GROUP BY i.[status], i.[barcode], i.[containerId], i.[comment], lpt.[Weight]
The most similar code I've written in LINQ is:
var lots = await (
from i in _dbContext.Items
join lpt in _dbContext.LagerOptions on i.ContainerId equals lpt.LagerId into lptTable
from lpt in lptTable.DefaultIfEmpty()
// The sum of all lagers for current lot
let lotWeight = (
from il in _dbContext.ItemsLines
join lp in _dbContext.LagerOptions on il.LagerId equals lp.LagerId into lpTable
from lp in lpTable.DefaultIfEmpty()
where il.ItemsId == i.Id
select (il.FactCount * lp.Weight.GetValueOrDefault(0))
).Sum()
where i.DocumentsId == documentId
select new
{
Status = i.Status,
Barcode = i.Barcode,
ContainerTypeId = i.ContainerId,
// total weight with container Weight
Weight = lotWeight + lpt.Weight.GetValueOrDefault(0),
//
Comment = i.Comment
}
).ToListAsync();
For SQL query the results can contain empty lots or lots with null-weight lagers (problem lagers) that makes "Weight" field of lot is equal NULL that helps detect problem lots.
But when I check the C# LINQ code EntityFramework create a COALESCE() function over SUM() function
and the query converted to SQL looks like this:
SELECT [t].[status] AS [Status], [t].[barcode] AS [Barcode], [t].[containerId] AS [ContainerTypeId], (
SELECT COALESCE(SUM([t0].[factCount] * COALESCE([l0].[Brutto], 0.0)), 0.0)
FROM [dbo].[ItemsLines] AS [t0]
LEFT JOIN [dbo].[LagerOptions] AS [l0] ON [t0].[lagerId] = [l0].[lagerId]
WHERE [t0].[itemsId] = [t].[id]) + COALESCE([l].[weight], 0.0) AS [Weight], [t].[comment] AS [Comment]
FROM [dbo].[Items] AS [t]
LEFT JOIN [dbo].[LagerOptions] AS [l] ON [t].[containerId] = [l].[lagerId]
WHERE [t].[documentId] = #__documentId_0
As a result, the weight of the problem lot will be equal to the container weight of this lot.
I can solve the problem with crutch methods, but I'm sure that there is a simple solution, which, unfortunately, I did not find.
I tryed to add different checks on null and rewrite the query for different JOIN patterns, but the main problem - EntityFramework create a COALESCE() function over SUM() function. And I don't know how to fix it in root. I work with C# EF approximately 1 month. EF 7.0.2
Help me, please.
!!EDITED
Correct LINQ query looks like this (Thank, Svyatoslav Danyliv):
var query =
from i in _dbContext.Items
join il in _dbContext.ItemsLines on i.Id equals il.ItemsId into ilj
from il in ilj.DefaultIfEmpty()
join lp in _dbContext.LagerOptions on il.LagerId equals lp.LagerId into lpj
from lp in lpj.DefaultIfEmpty()
join lpt in _dbContext.LagerOptions on i.ContainerId equals lpt.LagerId into lptj
from lpt in lptj.DefaultIfEmpty()
where i.DocumentsId == documentId
group new { lp, il, lpt } by new { i.Status, i.Barcode, i.ContainerId, i.Comment, lpt.Weight } into g
select new
{
g.Key.Status,
g.Key.Barcode,
ContainerTypeId = g.Key.ContainerId,
Weight = g.Sum(x => ((decimal?)x.lp.Weight) ?? 0 * x.il.FactCount) + g.Key.Weight ?? 0
g.Key.Comment,
};
But the query converted to SQL looks like this:
SELECT
[t].[status] AS [Status],
[t].[barcode] AS [Barcode],
[t].[containerId] AS [ContainerTypeId],
COALESCE(SUM(COALESCE([l].[weight], 0.0) * [t0].[factCount])), 0.0) +
COALESCE([l0].[weight], 0.0) AS [Weight],
[t].[comment] AS [Comment]
FROM [dbo].[Items] AS [t]
LEFT JOIN [dbo].[ItemsLines] AS [t0] ON [t].[id] = [t0].[itemsId]
LEFT JOIN [dbo].[LagerOptions] AS [l] ON [t0].[lagerId] = [l].[lagerId]
LEFT JOIN [dbo].[LagerOptions] AS [l0] ON [t].[containerId] = [l0].[lagerId]
WHERE [t].[documentsId] = #__documentId_0
GROUP BY [t].[status], [t].[barcode], [t].[containerId], [t].[comment], [l0].[weight]
EntityFramework create a COALESCE() function over SUM() function.
How to remove this?
This should equivalent LINQ query to your SQL. I do not understand why instead of grouping you have forced LINQ Translator to generate another query.
var query =
from i in _dbContext.Items
join il in _dbContext.ItemsLines on i.Id equals il.ItemsId into ilj
from il in ilj.DefaultIfEmpty()
join lp in _dbContext.LagerOptions on il.LagerId equals lp.LagerId into lpj
from lp in lpj.DefaultIfEmpty()
join lpt in _dbContext.LagerOptions on i.ContainerId equals lpt.LagerId into lptj
from lpt in lptj.DefaultIfEmpty()
where i.DocumentsId == documentId
group new { lp, il, lpt } by new { i.Status, i.Barcode, i.ContainerId, i.Comment, lpt.Weight } into g
select new
{
g.Key.Status,
g.Key.Barcode,
ContainerTypeId = g.Key.ContainerId,
Weight = g.Sum(x => ((double?)x.lp.Weight) ?? 0 * x.il.FactCount) + g.Key.Weight ?? 0
g.Key.Comment,
};
I'd like to group by state and sum up the total pledge amount, but if the pledge status is equal to canceled sum up the total paid. I'm not sure the best way to do this?
Thank you for feedback and help!
SELECT
dbo.FoundationCompanies.companyState,
CASE WHEN dbo.FondationOrder.pledgeStatus = 'canceled' THEN
(
SELECT SUM(paid) AS total
FROM dbo.FoundationInvoice
WHERE (orderId = dbo.FondationOrder.orderId)
)
ELSE
dbo.FondationOrder.pledgeAmount
END AS pledgeAmount
FROM
dbo.FoundationCompanies
INNER JOIN
dbo.FondationOrder
ON
dbo.FoundationCompanies.compId = dbo.FondationOrder.compId
GROUP BY dbo.FoundationCompanies.companyState
ORDER BY dbo.FoundationCompanies.companyState
Example data:
Algonquin 2500.00
Atlanta 500000.00
Batesville 10000.00
Batesville 25000.00
I would like the results to return as:
Amount |State
$100,000.00|AL
$145,000.00|AZ
Q : I'm not sure the best way to do this?
A : no,it'll use multi slow query ,you can use left join subquery to avoid it,like below script :
SELECT
companyState,
CASE WHEN FondationOrder.pledgeStatus = 'canceled' THEN
T.total
ELSE
FondationOrder.pledgeAmount
END AS pledgeAmount
FROM FoundationCompanies
INNER JOIN FoundationContacts ON FoundationCompanies.companyId = FoundationContacts.companyId
INNER JOIN FondationOrder ON FoundationContacts.contactId = FondationOrder.contactId
LEFT JOIN (
SELECT orderId,SUM(paid) AS total
FROM FoundationInvoice
GROUP BY orderId
) T on T.orderId = FondationOrder.orderId
GROUP BY FoundationCompanies.companyState
ORDER BY FoundationCompanies.companyState
Add Order table to your join then use the aggregate function :
SELECT
dbo.FoundationCompanies.companyState,
SUM(IIF(dbo.FondationOrder.pledgeStatus = 'canceled', dbo.FoundationInvoice.paid, dbo.FondationOrder.pledgeAmount)) AS pledgeAmount
FROM dbo.FoundationCompanies
INNER JOIN dbo.FoundationContacts ON dbo.FoundationCompanies.companyId = dbo.FoundationContacts.companyId
INNER JOIN dbo.FondationOrder ON dbo.FoundationContacts.contactId = dbo.FondationOrder.contactId
LEFT JOIN dbo.FoundationInvoice ON dbo.FondationOrder.orderId = dbo.FoundationInvoice.orderId
GROUP BY dbo.FoundationCompanies.companyState
I want to count my ReviewDetails.Review column but i got error:
Column 'AdvertiserMaster.AdvertiserID' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
Here Is My Query
SELECT DISTINCT
AdvertiserMaster.AdvertiserID, AdvertiserMaster.BusinessName , ISNULL(AdvertiserMaster.AverageRating, 0) AS AverageRating, AdvertiserMaster.ImageURL1, AdvertiserMaster.Address1,
AdvertiserMaster.CategoryID, AdvertiserMaster.Email, AdvertiserMaster.CountryID, AdvertiserMaster.StateID, AdvertiserMaster.CityID, AdvertiserMaster.PinCode, AdvertiserMaster.Mobile,
CategoryMaster.CategoryName, CountryMaster.CountryName, StateMaster.StateName, CityMaster.CityName,Count(ReviewDetails.Review) AS ReviewCount
FROM AdvertiserMaster INNER JOIN
BusinessCategoryDetails ON AdvertiserMaster.AdvertiserID = BusinessCategoryDetails.AdvertiserID INNER JOIN
ReviewDetails ON AdvertiserMaster.AdvertiserID = ReviewDetails.AdvertiserID LEFT OUTER JOIN
CategoryMaster ON AdvertiserMaster.CategoryID = CategoryMaster.CategoryID LEFT OUTER JOIN
CountryMaster ON AdvertiserMaster.CountryID = CountryMaster.CountryID LEFT OUTER JOIN
CityMaster ON AdvertiserMaster.CityID = CityMaster.CityID LEFT OUTER JOIN
StateMaster ON AdvertiserMaster.StateID = StateMaster.StateID LEFT OUTER JOIN
SubCategoryMaster ON BusinessCategoryDetails.SubCategoryID = SubCategoryMaster.SubCategoryID
WHERE (AdvertiserMaster.CategoryID = 8) AND (AdvertiserMaster.CityID = 16619) AND (AdvertiserMaster.IsActive = 1)
Since I am trying to get count by writing Count(ReviewDetails.Review)
But it is of no use.
here is my tables:ClassifiedBD Images
If you want to count something (or use other aggregate functions like sum), you need to define the level on which you count with group by clause, for example like this:
SELECT
AdvertiserMaster.AdvertiserID,
AdvertiserMaster.BusinessName,
ISNULL(AdvertiserMaster.AverageRating, 0) AS AverageRating,
AdvertiserMaster.ImageURL1,
AdvertiserMaster.Address1,
AdvertiserMaster.CategoryID,
AdvertiserMaster.Email,
AdvertiserMaster.CountryID,
AdvertiserMaster.StateID,
AdvertiserMaster.CityID,
AdvertiserMaster.PinCode,
AdvertiserMaster.Mobile,
CategoryMaster.CategoryName,
CountryMaster.CountryName,
StateMaster.StateName,
CityMaster.CityName,
COUNT(ReviewDetails.Review) AS ReviewCount
FROM AdvertiserMaster
INNER JOIN BusinessCategoryDetails
ON AdvertiserMaster.AdvertiserID = BusinessCategoryDetails.AdvertiserID
INNER JOIN ReviewDetails
ON AdvertiserMaster.AdvertiserID = ReviewDetails.AdvertiserID
LEFT OUTER JOIN CategoryMaster
ON AdvertiserMaster.CategoryID = CategoryMaster.CategoryID
LEFT OUTER JOIN CountryMaster
ON AdvertiserMaster.CountryID = CountryMaster.CountryID
LEFT OUTER JOIN CityMaster
ON AdvertiserMaster.CityID = CityMaster.CityID
LEFT OUTER JOIN StateMaster
ON AdvertiserMaster.StateID = StateMaster.StateID
LEFT OUTER JOIN SubCategoryMaster
ON BusinessCategoryDetails.SubCategoryID = SubCategoryMaster.SubCategoryID
WHERE (AdvertiserMaster.CategoryID = 8)
AND (AdvertiserMaster.CityID = 16619)
AND (AdvertiserMaster.IsActive = 1)
GROUP BY AdvertiserMaster.AdvertiserID,
AdvertiserMaster.BusinessName,
ISNULL(AdvertiserMaster.AverageRating, 0),
AdvertiserMaster.ImageURL1,
AdvertiserMaster.Address1,
AdvertiserMaster.CategoryID,
AdvertiserMaster.Email,
AdvertiserMaster.CountryID,
AdvertiserMaster.StateID,
AdvertiserMaster.CityID,
AdvertiserMaster.PinCode,
AdvertiserMaster.Mobile,
CategoryMaster.CategoryName,
CountryMaster.CountryName,
StateMaster.StateName,
CityMaster.CityName
You don't need distinct when you have group by.
You also might want to start using aliases for the tables and formatting / indenting your SQL properly
I am fairly new to LINQ and I am struggling to make a multiple JOIN.
So, this is how my database structure looks like:
Now, how should my query look like, if I have a particular Grade and I want to select
{Student.IndexNo, GradeValue.Value}, but if there is no grade value for a particular grade and particular user, null should be returned (Left join)?
The trick to get a LEFT join is to use the DefaultIfEmpty() method:
var otherValue = 5;
var deps = from tbl1 in Table1
join tbl2 in Table2
on tbl1.Key equals tbl2.Key into joinGroup
from j in joinGroup.DefaultIfEmpty()
where
j.SomeProperty == "Some Value"
&& tbl1.OtherProperty == otherValue
select j;
Deliberately posting this in 2015 for newbies looking for solution on google hits. I managed to hack and slash programming my way into solution.
var projDetails = from r in entities.ProjekRumah
join d in entities.StateDistricts on r.ProjekLocationID equals d.DistrictID
join j in entities.ProjekJenis on r.ProjekTypeID equals j.TypeID
join s in entities.ProjekStatus on r.ProjekStatusID equals s.StatusID
join approvalDetails in entities.ProjekApproval on r.ProjekID equals approvalDetails.ProjekID into approvalDetailsGroup
from a in approvalDetailsGroup.DefaultIfEmpty()
select new ProjectDetailsDTO()
{
ProjekID = r.ProjekID,
ProjekName = r.ProjekName,
ProjekDistrictName = d.DistrictName,
ProjekTypeName = j.TypeName,
ProjekStatusName = s.StatusName,
IsApprovalAccepted = a.IsApprovalAccepted ? "Approved" : "Draft",
ProjekApprovalRemarks = a.ApprovalRemarks
};
Produces following SQL code internally
{SELECT [Extent1].[ProjekID] AS [ProjekID]
,[Extent1].[ProjekName] AS [ProjekName]
,[Extent2].[DistrictName] AS [DistrictName]
,[Extent3].[TypeName] AS [TypeName]
,[Extent4].[StatusName] AS [StatusName]
,CASE
WHEN ([Extent5].[IsApprovalAccepted] = 1)
THEN N'Approved'
ELSE N'Draft'
END AS [C1]
,[Extent5].[ApprovalRemarks] AS [ApprovalRemarks]
FROM [dbo].[ProjekRumah] AS [Extent1]
INNER JOIN [dbo].[StateDistricts] AS [Extent2] ON [Extent1].[ProjekLocationID] = [Extent2].[DistrictID]
INNER JOIN [dbo].[ProjekJenis] AS [Extent3] ON [Extent1].[ProjekTypeID] = [Extent3].[TypeID]
INNER JOIN [dbo].[ProjekStatus] AS [Extent4] ON [Extent1].[ProjekStatusID] = [Extent4].[StatusID]
LEFT JOIN [dbo].[ProjekApproval] AS [Extent5] ON [Extent1].[ProjekID] = [Extent5].[ProjekID]
}
anybody can help me to convert some sql query whit right join like this to linq ?
SELECT dbo.FinnTrans.SanadID, dbo.FinnTrans.Date, dbo.FinnAccount.ID AS AccID,
dbo.FinnAccount.FullId, dbo.FinnAccount.Name, SUM(dbo.FinnTrans.Debit) AS TotalDebit,
SUM(dbo.FinnTrans.Credit) AS TotalCredit
FROM dbo.FinnAccount AS FinnAccount_1 LEFT OUTER JOIN
dbo.FinnAccount ON FinnAccount_1.ParentId = dbo.FinnAccount.ID RIGHT OUTER JOIN
dbo.FinnTrans LEFT OUTER JOIN
dbo.FinnAccount AS FinnAccount_2 ON dbo.FinnTrans.AccID = FinnAccount_2.ID ON
FinnAccount_1.ID = FinnAccount_2.ParentId
WHERE (dbo.FinnTrans.FPID = 7) AND (FinnAccount_2.AccLevel = 3)
GROUP BY dbo.FinnTrans.SanadID, dbo.FinnTrans.Date, dbo.FinnAccount.ID,
dbo.FinnAccount.Name, dbo.FinnAccount.FullId
HAVING (dbo.FinnTrans.SanadID = 1)
You can look here: http://www.hookedonlinq.com/OuterJoinSample.ashx as an example of the left outer join. And you can always swap tables to get either left or right
I've taken the liberty of beatifying your TSQL a little.
The last two join conditions appear malformed to me so this TSQL can not be parsed.
SELECT
[t].SanadID
, [t].Date
, [a].ID [AccID]
, [a].FullId
, [a].Name
, SUM([t].Debit) [TotalDebit]
, SUM([t].Credit) [TotalCredit]
FROM
dbo.FinnAccount [a1]
LEFT OUTER JOIN
dbo.FinnAccount [a]
ON [a1].ParentId = [a].ID
RIGHT OUTER JOIN
dbo.FinnTrans [t]
LEFT OUTER JOIN
dbo.FinnAccount [a2]
ON [a].AccID = [a2].ID
ON [a1].ID = [a2].ParentId
WHERE
[t].FPID = 7
AND
[a2].AccLevel = 3
GROUP BY
[t].SanadID
, [t].Date
, [a].ID
, [a].Name
, [a].FullId
HAVING
[t].SanadID = 1