Left outer joins with Linq-To-Sql - linq-to-sql

I want to use a linq-to-sql query which will use inner joins and left outer joins (using .DefaultIfEmpty()) but the query is not working. This is bugging me as its a simple task in T-SQL.
here is my query :
var results = from cy in _dc.Companies
join cyv in _dc.CompanyVersions
on cy.CompanyId equals cyv.CompanyId
join cyd in _dc.CompanyDetails
on cyv.CompanyVersionId equals cyd.Id
join cd in _dc.CustomerDetails
on cy.CompanyId equals cd.CompanyId
join d in _dc.Documents
on cd.CustomerId equals d.CustomerId
join di in _dc.DocumentItems
on d.DocumentId equals di.DocumentId
join dd in _dc.DocumentDetails
on di.DocDetailsId equals dd.DocumentDetailsId
join dt in _dc.DetailTypes
on dd.detailTypeId equals dt.detailTypeId
join vt in _dc.Vats
on dt.VATCode equals vt.VATCode
join v in _dc.Vouchers.DefaultIfEmpty()
on dd.DocumentDetailsId equals v.DocDetailID
join cc in _dc.CreditCards.DefaultIfEmpty()
on v.CCType equals cc.CCType
where
(d.DocTypeId == 1 || d.DocTypeId == 2) && (d.DocDate >= date)
&&
(d.DocDate < date.AddDays(1)) &&
(d.CompanyVersionId == cyv.CompanyVersionId)
&& (d.isDeleted == false || d.isDeleted == null)
orderby d.DocNumber ascending
select new
{
d.DocumentId,
d.DocNumber,
d.AutUser,
d.GrossAmount,
d.DocTypeId,
cyd.Name,
cyd.AddressLine1,
cyd.AddressLine2,
cyd.TelephoneLine,
cyd.FaxLine,
v.FromVoucNbr,
d.DocDate,
cd.CustomerName,
cd.StreetAddress,
cd.City,
cd.Country,
dt.DetDescr,
cc.CCType,
dd.FreeDescr,
dd.NetAmount,
dd.VATAmount,
vt.VATDescr,
cc.Description,
vt.VATRate
};
can anyone suggest how i can use left outer joins on the last 2 tables in this query?

You placed both .DefaultIfEmpty wrong.
I think it is something like this (although I'm not sure about the where clause..).
var results =
from cy in _dc.Companies
join cyv in _dc.CompanyVersions on cy.CompanyId equals cyv.CompanyId
join cyd in _dc.CompanyDetails on cyv.CompanyVersionId equals cyd.Id
join cd in _dc.CustomerDetails on cy.CompanyId equals cd.CompanyId
join d in _dc.Documents on cd.CustomerId equals d.CustomerId
join di in _dc.DocumentItems on d.DocumentId equals di.DocumentId
join dd in _dc.DocumentDetails on di.DocDetailsId equals dd.DocumentDetailsId
join dt in _dc.DetailTypes on dd.detailTypeId equals dt.detailTypeId
join vt in _dc.Vats on dt.VATCode equals vt.VATCode
join v in _dc.Vouchers on dd.DocumentDetailsId equals v.DocDetailID into other1
from o1 in other1.DefaultIfEmpty()
join cc in _dc.CreditCards on v.CCType equals cc.CCType into other2
from o2 in other2.DefautlIfEmtpy()
where (d.DocTypeId == 1 || d.DocTypeId == 2)
&& (d.DocDate >= date)
&& (d.DocDate < date.AddDays(1))
&& (d.CompanyVersionId == cyv.CompanyVersionId)
&& (d.isDeleted == false || d.isDeleted == null)
orderby d.DocNumber ascending
select new
{
d.DocumentId,
d.DocNumber,
d.AutUser,
d.GrossAmount,
d.DocTypeId,
cyd.Name,
cyd.AddressLine1,
cyd.AddressLine2,
cyd.TelephoneLine,
cyd.FaxLine,
o1.FromVoucNbr,
d.DocDate,
cd.CustomerName,
cd.StreetAddress,
cd.City,
cd.Country,
dt.DetDescr,
o2.CCType,
dd.FreeDescr,
dd.NetAmount,
dd.VATAmount,
vt.VATDescr,
o2.Description,
vt.VATRate
};

yes the order of the joins was incorrect and i've fixed it now here is the working and compiled query:
P.s. thanks everyone for your help!
var results =
from cy in _dc.Companies
join cyv in _dc.CompanyVersions on cy.CompanyId equals cyv.CompanyId
join cyd in _dc.CompanyDetails on cyv.CompanyVersionId equals cyd.Id
join cd in _dc.CustomerDetails on cy.CompanyId equals cd.CompanyId
join d in _dc.Documents on cd.CustomerId equals d.CustomerId
join di in _dc.DocumentItems on d.DocumentId equals di.DocumentId
join dd in _dc.DocumentDetails on di.DocDetailsId equals
dd.DocumentDetailsId
join dt in _dc.DetailTypes on dd.detailTypeId equals dt.detailTypeId
join vt in _dc.Vats on dt.VATCode equals vt.VATCode
join v in _dc.Vouchers on dd.DocumentDetailsId equals v.DocDetailID into
other1
from o1 in other1.DefaultIfEmpty()
join cc in _dc.CreditCards on o1.CCType equals cc.CCType into other2
from o2 in other2.DefaultIfEmpty()
where (d.DocTypeId == 1 || d.DocTypeId == 2)
&& (d.DocDate >= date)
&& (d.DocDate < date.AddDays(1))
&& (d.CompanyVersionId == cyv.CompanyVersionId)
&& (d.isDeleted == false || d.isDeleted == null)
orderby d.DocNumber ascending
select new
{
d.DocumentId,
d.DocNumber,
d.AutUser,
d.GrossAmount,
d.DocTypeId,
cyd.Name,
cyd.AddressLine1,
cyd.AddressLine2,
cyd.TelephoneLine,
cyd.FaxLine,
o1.FromVoucNbr,
d.DocDate,
cd.CustomerName,
cd.StreetAddress,
cd.City,
cd.Country,
dt.DetDescr,
o2.CCType,
dd.FreeDescr,
dd.NetAmount,
dd.VATAmount,
vt.VATDescr,
o2.Description,
vt.VATRate
};

Related

Linq to Sql 3 joins with group and min()

I'm trying to convert the SQL below to Linq. I haven't figured out the syntax for the GROUP BY, the MIN() or the extra organization join conditions.
SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr, MIN(a.SystemCreatedOnDtm) MinCreated
FROM vw_DimLabAsset a
INNER JOIN vw_FactWorker w ON a.LabAssetAssignedToWorkerKey = w.WorkerKey
INNER JOIN vw_DimOrganizationHierarchy o ON w.OrganizationHierarchyKey = o.OrganizationHierarchyKey
AND o.OrganizationHierarchyUnitLevelThreeNm IS NOT NULL
AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
This is what I've managed to get so far:
var pphw = from a in Vw_DimLabAsset
where a.LabAssetHardwareStatus != "Retired" && (a.LabAssetHardwareSubStatus == null || a.LabAssetHardwareSubStatus != "Archive") && types.Contains(a.LabAssetTypeNm) // (a.LabAssetTypeNm == "u_cmdb_ci_prototype_system" || a.LabAssetTypeNm == "u_cmdb_ci_silicon")
join w in Vw_FactWorker on a.LabAssetAssignedToWorkerKey equals w.WorkerKey
join o in Vw_DimOrganizationHierarchy on w.OrganizationHierarchyKey equals o.OrganizationHierarchyKey
select new { o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr };
Here is how I would translate the query:
var ans = (from a in vw_DimLabAsset
join w in vw_FactWorker on a.LabAssetAssignedToWorkerKey equals w.WorkerKey
join o in vw_DimOrganizationHierarchy on w.OrganizationHierarchyKey equals o.OrganizationHierarchyKey
where o.OrganizationHierarchyUnitLevelThreeNm != null && o.OrganizationHierarchyUnitLevelFourNm != null
group new { o, a } by new { o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr } into oag
select new {
oag.Key.OrganizationHierarchyUnitLevelThreeNm,
oag.Key.OrganizationHierarchyUnitLevelFourNm,
oag.Key.LabAssetSerialNbr,
MinCreated = oag.Min(oa => oa.a.SystemCreatedOnDtm)
}).Distinct();

OR opertor ignores AND operator MYSQL

see the query below i want all those records where status is either using or offering and userid is not equals to 1 and coursecode is cs3333
SELECT c.`id` AS courseid,
c.`userid` AS userid,
c.`coursecode`,
m.`title`,
s.`sem_name`,
p.`professor`,
st.`status`,
a.`author_name`,
q.`quality`,
m.`comments`,
m.`price`,
m.`material`
FROM sc_courses c
JOIN sc_c_materials m
ON c.`id`=m.`courseid`
JOIN sc_semesters s
ON s.`id`=c.`semid`
JOIN sc_professors p
ON c.`profid`=p.`id`
JOIN sc_status st
ON c.`statusid`=st.`id`
LEFT JOIN sc_authors a
ON m.`authorid`=a.`id`
JOIN sc_quality q
ON m.`qualityid`=q.`id`
WHERE st.`status` = "offering" OR st.`status` = "using" AND c.`userid` != "1" AND c.`coursecode` = "CS3333";
the query is running but it ignores both the and operators the above query return all records where userid is 1 and coursecode is not equal to cs3333 but i dont want these records plz tell me what am i doing wrong????
You just need brackets
WHERE (st.`status` = "offering" OR st.`status` = "using") AND c.`userid` != "1" AND c.`coursecode` = "CS3333";
That is because priority. You should place ( .. ) to change order of comparison.
(st.`status` = "offering" OR st.`status` = "using")
AND c.`userid` != "1"
AND c.`coursecode` = "CS3333"
opss stupid mistake here it is working with this query
SELECT c.`id` AS courseid,
c.`userid` AS userid,
c.`coursecode`,
m.`title`,
s.`sem_name`,
p.`professor`,
st.`status`,
a.`author_name`,
q.`quality`,
m.`comments`,
m.`price`,
m.`material`
FROM sc_courses c
JOIN sc_c_materials m
ON c.`id`=m.`courseid`
JOIN sc_semesters s
ON s.`id`=c.`semid`
JOIN sc_professors p
ON c.`profid`=p.`id`
JOIN sc_status st
ON c.`statusid`=st.`id`
LEFT JOIN sc_authors a
ON m.`authorid`=a.`id`
JOIN sc_quality q
ON m.`qualityid`=q.`id`
WHERE c.`userid` != "1" AND c.`coursecode` = "CS3333" AND st.`status` = "offering" OR
c.`userid` != "1" AND c.`coursecode` = "CS3333" AND st.`status` = "using";

MySQL not recognizing virtual column / field

I'm trying to manipulate two virtual fields generated of a subquery into a new field, but MySQL is telling me that "GP" is an unknown column, but it has been already declared. Please, take a look at my query:
SELECT *,
(SELECT COUNT(id_gol) FROM tb_gol as gol
INNER JOIN tb_jogo as jg ON(gol.fk_id_jogo = jg.id_jogo)
WHERE gol.ic_excluido != '*' AND gol.fk_id_equipe = e.id_equipe AND jg.fk_id_campeonato = g.fk_id_campeonato) as 'GP',
(SELECT COUNT(id_gol) FROM tb_gol as gol
INNER JOIN tb_jogo as jg ON(gol.fk_id_jogo = jg.id_jogo)
WHERE gol.ic_excluido != '*' AND gol.fk_id_equipe != e.id_equipe AND (jg.fk_id_equipe1 = e.id_equipe OR jg.fk_id_equipe2 = e.id_equipe) AND jg.fk_id_campeonato = g.fk_id_campeonato) as 'GC',
(SELECT COUNT(id_wo) as WOs FROM tb_wo as w INNER JOIN tb_jogo as j ON (w.fk_id_jogo = j.id_jogo) WHERE w.fk_id_equipe = e.id_equipe AND j.fk_id_campeonato = g.fk_id_campeonato) as 'WO',
(GP+(GC*-1)) as 'SALDO'
FROM tb_equipe as e
INNER JOIN tb_gruposEquipes as ge ON (e.id_equipe = ge.fk_id_equipe)
INNER JOIN tb_grupos as g ON (g.id_grupo = ge.fk_id_grupo)
WHERE g.fk_id_campeonato = 23
ORDER BY WO ASC
As you can see, "SALDO" would be the result of "GP-GC". But MySQL do not recognize these columns
How can I solve this?
SOLUTION
Thanks a lot for the help, guys, but I figured out the problem.
"SALDO" couldn't be created by substracting GC of GP because "GP" and "GC" doesn't exist during runtime.
So, when you need to manipulate virtual fields during the runtime, you'll have to repeat the code that generated the virtual field.
Then, if you have this select:
SELECT *, (field1+1) as 'GP', (field2+1) as 'GC', (GP+GC) as 'SALDO' FROM (...)
You'll need to replace it with this:
SELECT *, (field1+1) as 'GP', (field2+1) as 'GC', ((field1+1)+(field2+1)) as 'SALDO' FROM (...)
Push the stuff into in inner query
SELECT core.*,
(GP+(GC*-1)) as 'SALDO'
from (
(SELECT COUNT(id_gol) FROM tb_gol as gol
INNER JOIN tb_jogo as jg ON(gol.fk_id_jogo = jg.id_jogo)
WHERE gol.ic_excluido != '*' AND gol.fk_id_equipe = e.id_equipe AND jg.fk_id_campeonato = g.fk_id_campeonato) as 'GP',
(SELECT COUNT(id_gol) FROM tb_gol as gol
INNER JOIN tb_jogo as jg ON(gol.fk_id_jogo = jg.id_jogo)
WHERE gol.ic_excluido != '*' AND gol.fk_id_equipe != e.id_equipe AND (jg.fk_id_equipe1 = e.id_equipe OR jg.fk_id_equipe2 = e.id_equipe) AND jg.fk_id_campeonato = g.fk_id_campeonato) as 'GC',
(SELECT COUNT(id_wo) as WOs FROM tb_wo as w INNER JOIN tb_jogo as j ON (w.fk_id_jogo = j.id_jogo) WHERE w.fk_id_equipe = e.id_equipe AND j.fk_id_campeonato = g.fk_id_campeonato) as 'WO' )
FROM tb_equipe as e
) as core
INNER JOIN tb_gruposEquipes as ge ON (core.id_equipe = ge.fk_id_equipe)
INNER JOIN tb_grupos as g ON (g.id_grupo = ge.fk_id_grupo)
WHERE g.fk_id_campeonato = 23
ORDER BY WO ASC

Conditional JOINs based on column value

I'm trying to conditionally join one master event table to three others depending on an event type. The select statement works fine, and returns the result set I'd expect, but when I add the JOIN statements, I get an error saying the column aliases were not found:
SELECT
event.type as type,
IF(type = 'birthday', event.target_id, NULL) as birthday_id,
IF(type = 'graduation', event.target_id, NULL) as graduation_id,
IF(type = 'wedding', event.target_id, NULL) as wedding_id
FROM event
LEFT OUTER JOIN birthday ON birthday_id = birthday.id
LEFT OUTER JOIN graduation ON graduation_id = graduation.id
LEFT OUTER JOIN wedding ON wedding_id = wedding.id
Gets this error:
Unknown column 'birthday_id' in 'on clause'
UPDATE: Ok Sebas just indicated you can't join on calculation results, in which case my approach is off. So what is the correct approach for doing something like this?
SELECT
event.type as type,
IF(type = 'birthday', birthday.id, NULL) as birthday_id,
IF(type = 'graduation', graduation.id, NULL) as graduation_id,
IF(type = 'wedding', wedding.id, NULL) as wedding_id
FROM
event
LEFT OUTER JOIN birthday b ON event.target_id = b.id
LEFT OUTER JOIN graduation g ON b.id IS NULL AND event.target_id = g.id
LEFT OUTER JOIN wedding w ON b.id IS NULL AND g.id IS NULL AND event.target_id = w.id
should do the trick, give me feedback!
rgds.
edit: See the IS NULL conditions. I didn't test it, I wonder if mysql would accept it! If yes, then almost only the necessary joins would be done...
You need to join all of the tables with the same field, event.target_id, and when you need to show some specific data, you can test the type before.
Example:
SELECT
event.type as type,
IF(type = 'birthday', birthday.birthday_id, NULL) as birthday,
IF(type = 'graduation', graduation.graduation_id, NULL) as graduation,
IF(type = 'wedding', wedding.wedding_id, NULL) as wedding
FROM event
LEFT OUTER JOIN birthday ON birthday_id = event.target_id
LEFT OUTER JOIN graduation ON graduation_id = event.target_id
LEFT OUTER JOIN wedding ON wedding_id = event.target_id
Not testes, but hope this helps you elucidate your doubts.
Sebas answer is correct but need not conditions to check IS NULL for each previous joins, you can use based column value to make it effective. I have tested this and its working.
SELECT
E.type AS type,
IF(E.type = 'birthday', B.id, NULL) AS birthday_id,
IF(E.type = 'graduation', G.id, NULL) AS graduation_id,
IF(E.type = 'wedding', W.id, NULL) AS wedding_id
FROM event E
LEFT OUTER JOIN birthday B ON E.type = 'birthday' AND E.target_id = B.id
LEFT OUTER JOIN graduation G ON E.type = 'graduation' AND E.target_id = G.id
LEFT OUTER JOIN wedding W ON E.type = 'wedding' AND E.target_id = W.id

Multiply different datatype in query of linq to sql

I have a query :
var list_transaction = from i in Dt.Transactions
join c in this.Dt.Customers on i.CustomerID equals c.ID
join e in this.Dt.Employees on i.EmployeeID equals e.ID
join p in this.Dt.Projects on i.ProjectID equals p.ID
where
i.CustomerID == idCus &&
i.TransactionStep == 3 &&
i.EmployeeID == e.ID &&
i.ProjectID == p.ID
select new {
VAT = (i.Taxable * i.Total * p.VATRate/100)
};
Problem : the VAT is the multiply of three value that have different datatype. Taxable is int, Total is money and VATRate is float.
So could anyone tell me, how can I cast that in this query?
Thanks so much.
Try this :
System.Convert.ToDouble(i.Total) + (i.Taxable * System.Convert.ToDouble(i.Total)
* p.VATRate / 100)