I have this query
SELECT t.NomeTipo, sum(v.QtdProduto)
FROM [dbo].[Vendas] AS V
RIGHT JOIN [dbo].[Produtos] AS P ON V.IdProduto = P.IdProduto
INNER JOIN [dbo].[Tipos] AS T ON P.IdTipo = T.IdTipo
group by t.NomeTipo
order by t.NomeTipo
I have tried this
var queryTipos = from vendas in repositorioVendas.Vendas
join produtos in repositorioProduto.Produtos.DefaultIfEmpty()
on vendas.IdProduto equals produtos.IdProduto
join tipos in repositorioTipo.Tipos
on produtos.IdTipo equals tipos.IdTipo
group vendas by new { tipos.NomeTipo, vendas.QtdProduto }
into novoGrupo
select new
{
NomeTipo = novoGrupo.Key.NomeTipo,
QtdProduto = novoGrupo.Sum(x => x.QtdProduto)
};
With this query I got only two results, but when I run straight from the database I get something like this:
Bebidas 16
Bolos 14
Frios 16
Pães 21
The trick is to realize that you can rewrite your query with a left join instead of a right join by swapping the order of the first two tables and that Linq doesn't have a way to really handle right joins. Also you're grouping was wrong.
var queryTipos = from produtos in repositorioProduto.Produtos
join vendas_pj in repositorioVendas.Vendas
on vendas_pj.IdProduto equals produtos.IdProduto into joined
from vendas in joined.DefaultIfEmpty()
join tipos in repositorioTipo.Tipos
on produtos.IdTipo equals tipos.IdTipo
group vendas by tipos.NomeTipo
into novoGrupo
select new
{
NomeTipo = novoGrupo.Key,
QtdProduto = novoGrupo.Sum(x => x.QtdProduto)
};
Basically a Left join in SQL
From TableA
Left Join TableB
On TableA.ID = TableB.ID
is done in Linq like this
from a in repo.TableA
join b_pj in repo.TableB
on a.ID equals b_pj.ID into joined
from b in joined.DefaultIfEmpty()
I have a SQL statement
SELECT
cci.[ID], cci.[OwnerFirstName], cci.[OwnerLastName], cci.[CompanyName],
cci.[AddressLine1], cci.[AddressLine2], cci.[AddressLine3], cci.[AddressLine4],
cci.[AddressLine5], cci.[AddressCity], sp1.[Abbreviation] AS [StateAbbreviation],
sp2.[Abbreviation] AS [ProvinceAbbreviation], cci.[AddressPostalCode],
cr1.[Name] AS [CountryName], cr2.[Name] AS [RegionName], cci.[AddressNote],
cci.[Phone1], cci.[Phone2], cci.[Phone3], cci.[Phone4], cci.[Phone5],
cci.[Fax1], cci.[Fax2], cci.[Fax3], cci.[Fax4], cci.[Fax5], cci.[Email1],
cci.[Email2], cci.[Email3], cci.[Email4], cci.[Email5], cci.[CompanyWebSite],
ci.[EIN], ci.[SSN], cli.[LegalName], cli.[LegalAddressLine1], cli.[LegalAddressLine2],
cli.[LegalAddressLine3], cli.[LegalAddressLine4], cli.[LegalAddressLine5],
cli.[LegalAddressCity], sp3.[Abbreviation] AS [LegalAddressStateAbbreviation],
sp4.[Abbreviation] AS [LegalAddressProvinceAbbreviation], cli.[LegalAddressPostalCode],
cr3.[Name] AS [LegalAddressCountryName], cr4.[Name] AS [LegalAddressRegionName],
cli.[LegalAddressNote], cri.[FirstMonthFiscalYear], cri.[FirstMonthIncomeTaxYear],
CONCAT(CONCAT(CONCAT(itfl.[TaxForm], ' - ('),itfl.[Description]), ')') AS [TaxForm],
c.[CryptoPassPhrase], c.[CryptoVector], c.[CryptoMinSALTLen],
c.[CryptoMaxSALTLen], c.[CryptoKeySize], c.[CryptoHash], c.[CryptoSALT],
c.[CryptoIterations], ga.[AccountCode], ga.[UseAnalytics],
CONCAT(CONCAT(CONCAT(CONCAT(e1.[LastName], ', '), e1.[FirstName]), ' '), e1.[MiddleName]) AS [CreatedBy],
sd.[CreatedByID], sd.[CreatedDateTime],
CONCAT(CONCAT(CONCAT(CONCAT(e2.[LastName], ', '), e2.[FirstName]), ' '), e2.[MiddleName]) AS [ModifiedBy],
sd.[ModifiedByID], sd.[ModifiedDateTime], sd.[SiteDescription],
s.[SMTPServer], s.[SMTPUserName], s.[SMTPUserName], s.[SMTPPassword],
s.[SMTP_TO], s.[SMTP_CC], s.[SMTP_BCC], s.[SMTPEncoding]
FROM [settings].[CompanyContactInformation] cci
LEFT OUTER JOIN [settings].[CompanyIdentification] ci ON cci.[ID] = ci.[SiteID]
LEFT OUTER JOIN [settings].[CompanyLegalInformation] cli ON cci.[ID] = cli.[ID]
LEFT OUTER JOIN [settings].[CompanyReportInformation] cri ON cci.[ID] = cri.[SiteID]
LEFT OUTER JOIN [settings].[Cryptography] c ON cci.[ID] = c.[SiteID]
LEFT OUTER JOIN [settings].[GoogleAnalytics] ga ON cci.[ID] = ga.[SiteID]
LEFT OUTER JOIN [settings].[IncomeTaxFormList] itfl ON cri.[TaxFormID] = itfl.[ID]
LEFT OUTER JOIN [settings].[SiteDetails] sd ON cci.[ID] = sd.[SiteID]
LEFT OUTER JOIN [settings].[SMTP] s ON cci.[ID] = s.[SiteID]
LEFT OUTER JOIN [dbo].[Employee] e1 ON sd.[CreatedByID] = e1.[ID]
LEFT OUTER JOIN [dbo].[Employee] e2 ON sd.[ModifiedByID] = e2.[ID]
LEFT OUTER JOIN [dbo].[CountryOrRegion] cr1 ON cci.[AddressCountryID] = cr1.[ID]
LEFT OUTER JOIN [dbo].[CountryOrRegion] cr2 ON cci.[AddressRegionID] = cr2.[ID]
LEFT OUTER JOIN [dbo].[CountryOrRegion] cr3 ON cli.[LegalAddressCountryID] = cr3.[ID]
LEFT OUTER JOIN [dbo].[CountryOrRegion] cr4 ON cli.[LegalAddressRegionID] = cr4.[ID]
LEFT OUTER JOIN [dbo].[StateOrProvince] sp1 ON cci.[AddressStateID] = sp1.[ID]
LEFT OUTER JOIN [dbo].[StateOrProvince] sp2 ON cci.[AddressProvinceID] = sp2.[ID]
LEFT OUTER JOIN [dbo].[StateOrProvince] sp3 ON cli.[LegalAddressStateID] = sp3.[ID]
LEFT OUTER JOIN [dbo].[StateOrProvince] sp4 ON cli.[LegalAddressProvinceID] = sp4.[ID]
So far I have the following LINQ statement in LinqPad:
var q = (
from cci in CompanyContactInformation
join sp1 in StateOrProvince on cci.AddressStateID equals sp1.ID into t1
from rt1 in t.DefaultIfEmpty()
select new {
cci.ID, cci.OwnerFirstName, cci.OwnerLastName, cci.CompanyName,
cci.AddressLine1, cci.AddressLine2,cci.AddressLine3,
cci.AddressLine4, cci.AddressLine5, cci.AddressCity,
StateAbbreviation = sp1.Abbreviation
}).ToList();
q.Dump();
And I am getting the following error:
'LINQPad.User.StateOrProvince' is a 'type' but is used like a 'variable'
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'GroupJoin'.
What am I doing wrong here?
Solved it after pulling my hair out. Had to pluralize some of the tables. Here is the proper LINQ statement:
var q = (
from cci in CompanyContactInformation
join ci in CompanyIdentifications on cci.ID equals ci.SiteID into t1 from rt1 in t1.DefaultIfEmpty()
join cli in CompanyLegalInformation on cci.ID equals cli.ID into t2 from rt2 in t2.DefaultIfEmpty()
join cri in CompanyReportInformation on cci.ID equals cri.SiteID into t3 from rt3 in t3.DefaultIfEmpty()
join c in Cryptographies on cci.ID equals c.SiteID into t4 from rt4 in t4.DefaultIfEmpty()
join ga in GoogleAnalytics on cci.ID equals ga.SiteID into t5 from rt5 in t5.DefaultIfEmpty()
join itfl in IncomeTaxFormLists on rt3.TaxFormID equals itfl.ID into t6 from rt6 in t6.DefaultIfEmpty()
join sd in SiteDetails on cci.ID equals sd.SiteID into t7 from rt7 in t7.DefaultIfEmpty()
join s in SMTPs on cci.ID equals s.SiteID into t8 from rt8 in t8.DefaultIfEmpty()
join e1 in Employees on rt7.CreatedByID equals e1.ID into t9 from rt9 in t9.DefaultIfEmpty()
join e2 in Employees on rt7.ModifiedByID equals e2.ID into t10 from rt10 in t10.DefaultIfEmpty()
join cr1 in CountryOrRegions on cci.AddressCountryID equals cr1.ID into t11 from rt11 in t11.DefaultIfEmpty()
join cr2 in CountryOrRegions on cci.AddressRegionID equals cr2.ID into t12 from rt12 in t12.DefaultIfEmpty()
join cr3 in CountryOrRegions on rt2.LegalAddressCountryID equals cr3.ID into t13 from rt13 in t13.DefaultIfEmpty()
join cr4 in CountryOrRegions on rt2.LegalAddressRegionID equals cr4.ID into t14 from rt14 in t14.DefaultIfEmpty()
join sp1 in StateOrProvinces on cci.AddressStateID equals sp1.ID into t15 from rt15 in t15.DefaultIfEmpty()
join sp2 in StateOrProvinces on cci.AddressProvinceID equals sp2.ID into t16 from rt16 in t16.DefaultIfEmpty()
join sp3 in StateOrProvinces on rt2.LegalAddressStateID equals sp3.ID into t17 from rt17 in t17.DefaultIfEmpty()
join sp4 in StateOrProvinces on rt2.LegalAddressProvinceID equals sp4.ID into t18 from rt18 in t18.DefaultIfEmpty()
select new {
cci.ID, cci.OwnerFirstName, cci.OwnerLastName, cci.CompanyName, cci.AddressLine1, cci.AddressLine2,
cci.AddressLine3, cci.AddressLine4, cci.AddressLine5, cci.AddressCity, StateAbbreviation = rt15.Abbreviation,
ProvinceAbbreviation = rt16.Abbreviation, cci.AddressPostalCode, CountryName = rt11.Name,
RegionName = rt12.Name, cci.AddressNote, cci.Phone1, cci.Phone2, cci.Phone3, cci.Phone4, cci.Phone5,
cci.Fax1, cci.Fax2, cci.Fax3, cci.Fax4, cci.Fax5, cci.Email1, cci.Email2, cci.Email3, cci.Email4,
cci.Email5, cci.CompanyWebSite, rt1.EIN, rt1.SSN, rt2.LegalName, rt2.LegalAddressLine1, rt2.LegalAddressLine2,
rt2.LegalAddressLine3, rt2.LegalAddressLine4, rt2.LegalAddressLine5, rt2.LegalAddressCity,
LegalAddressStateAbbreviation = rt17.Abbreviation, LegalAddressProvinceAbbreviation = rt18.Abbreviation,
rt2.LegalAddressPostalCode, LegalAddressCountryName = rt13.Name, LegalAddressRegionName = rt14.Name,
rt2.LegalAddressNote, rt3.FirstMonthFiscalYear, rt3.FirstMonthIncomeTaxYear,
TaxForm = rt6.TaxForm + " - (" + rt6.Description + ")",
rt4.CryptoPassPhrase, rt4.CryptoVector, rt4.CryptoMinSALTLen, rt4.CryptoMaxSALTLen, rt4.CryptoKeySize, rt4.CryptoHash,
rt4.CryptoSALT, rt4.CryptoIterations, rt5.AccountCode, rt5.UseAnalytics,
CreatedBy = rt9.LastName + ", " + rt9.FirstName + " " + rt9.MiddleName,
rt7.CreatedByID, rt7.CreatedDateTime,
ModifiedBy = rt10.LastName + ", " + rt10.FirstName + " " + rt10.MiddleName,
rt7.ModifiedByID, rt7.ModifiedDateTime, rt7.SiteDescription, rt8.SMTPServer, rt8.SMTPUserName,
rt8.SMTPPassword, rt8.SMTP_TO, rt8.SMTP_CC, rt8.SMTP_BCC, rt8.SMTPEncoding
}).ToList();
q.Dump();
I have 2 inner joins (3 tables) but I don't know and I find it hard to implement my research about outer join in LINQ. How do I change the last inner join to outer join, such that column will still join even if the column (Role) is null?
Here's an existing SQL version of this which I want to convert to LINQ:
SELECT dbo.EmployeeAccess.id, dbo.EmployeeAccess.EmpNo, dbo.EmployeeAccess.RoleID, dbo.EmployeeAccess.Active, dbo.EmployeeAccessLevel.Role,
dbo.View_HCM.LNameByFName
FROM dbo.EmployeeAccess LEFT OUTER JOIN
dbo.EmployeeAccessLevel ON dbo.EmployeeAccess.RoleID = dbo.EmployeeAccessLevel.id INNER JOIN
dbo.View_HCM ON dbo.EmployeeAccess.EmpNo = dbo.View_HCM.EmpNo
LINQ I now have with 2 inner joins:
(from ea in context.EmployeeAccesses
join vh in context.View_HCM on (Int16)ea.EmpNo equals vh.EmpNo
join rl in context.EmployeeAccessLevels on ea.RoleID equals rl.id
select new EmployeeWithEmail{
EmpNum = ea.EmpNo ?? 0,
EmailAddress = vh.EmailAddress,
LNameByFname = vh.LNameByFName,
Active2 = ea.Active ?? false
}).ToList();
}
Linq's outer join syntax uses 2 parts. First an into then DefaultIfEmpty
In your case, an outer join might look like this:
(from ea in context.EmployeeAccesses
join vh in context.View_HCM on (Int16)ea.EmpNo equals vh.EmpNo
join rl in context.EmployeeAccessLevels on ea.RoleID equals rl.id into outer_join
from subjoin in outer_join.DefaultIfEmpty()
select new EmployeeWithEmail{
EmpNum = ea.EmpNo ?? 0,
EmailAddress = vh.EmailAddress,
LNameByFname = vh.LNameByFName,
Active2 = ea.Active ?? false
}).ToList();
There are many tutorials on how to create the outer join in LINQ.
I have following SQL Query
SELECT * FROM KDMS_dynamic vd
INNER JOIN KDMS_definition tblKDMS ON tblKDMS.SystemID=vd.SystemID
LEFT OUTER JOIN KDMS_typeid tblKDMSType ON tblKDMS.TypeId=tblKDMSType.TypeId
INNER JOIN KDMS_configuration tblKDMSConfig ON tblKDMS.SystemID=tblKDMSConfig.SystemID
AND tblKDMSConfig.ConfigurationDate = (SELECT MAX(ConfigurationDate)
FROM KDMS_configuration vc
WHERE vc.SystemID=tblKDMSConfig.SystemID)
AND vd.LastUpdated=(SELECT MAX(LastUpdated) FROM KDMS_dynamic vd
WHERE vd.SystemID=tblKDMS.SystemID)
WHERE
DeletionDate IS NULL
AND LongDescription IS NOT NULL
AND tblKDMS.TypeId <> 1
As I have try convert the same in to LINQ but I can not due to AND OPERATOR use in Inner Join.
I am not aware how to use And Operator in LINQ , JOIN
As folloing the linq code which i try.
IQueryable<getKDMS> query = (from VD in this._db.GetTable<KDMS_dynamic>()
join TblKDMS in this._db.GetTable<KDMS_definition>() on VD.SystemID equals TblKDMS.SystemID
join TblKDMSType in this._db.GetTable<KDMS_typeid>().DefaultIfEmpty() on TblKDMS.TypeID equals TblKDMSType.TypeID
join TblKDMSConfig in this._db.GetTable<KDMS_configuration>() on TblKDMS.SystemID equals TblKDMSConfig.SystemID
&& TblKDMSConfig.ConfigurationDate == (from TblKDMS_conf in this._db.GetTable<KDMS_configuration>()
where TblKDMS_conf.SystemID == TblKDMSConfig.SystemID
select TblKDMS_conf.ConfigurationDate).Max())
As i have try with && but it did not work....
it is done as on new{x.field1,x.field2} equals new{y.field1,y.field2}
var somedata = (from TblKDMS_conf in this._db.GetTable<KDMS_configuration>()
where TblKDMS_conf.SystemID == TblKDMSConfig.SystemID select TblKDMS_conf.ConfigurationDate).Max();
Queryable<getKDMS> query = (from VD in this._db.GetTable<KDMS_dynamic>()
join TblKDMS in this._db.GetTable<KDMS_definition>() on VD.SystemID equals TblKDMS.SystemID
join TblKDMSType in this._db.GetTable<KDMS_typeid>().DefaultIfEmpty() on TblKDMS.TypeID equals TblKDMSType.TypeID
join TblKDMSConfig in this._db.GetTable<KDMS_configuration>() on new {TblKDMS.SystemID,TblKDMSConfig.ConfigurationDate} equals new{TblKDMSConfig.SystemID,somedata}
Move the AND condition to your WHERE clause. Writing
SELECT * FROM Table1
INNER JOIN Table2 ON *first condition* AND *second condition*
WHERE *third condition*
is exactly the same as writing
SELECT * FROM Table1
INNER JOIN Table2 ON *first condition*
WHERE *second condition* AND *third condition*
I think you need to use the where operator in place of the &&.