Linq to Sql 3 joins with group and min() - linq-to-sql

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();

Related

how i write this sql query to linq query

i just want to use LinqToSql classes query. here i just want to convert this sql query to appropriate linq query.
this is my sql query:
SELECT j.[JobID], p.[PreparedEmailID],
p.[Name] AS 'PreparedEmailName',
j.[CreatedOn], j.[CompletedOn],
j.[SubscriberCount], j.[EmailsSent],
(SELECT TOP 1 [Message] FROM
[LoggedMessages] WHERE [JobID] =
j.[JobID] ORDER BY [LoggedMessageID] DESC)
AS 'LoggedMessage' FROM [Jobs] AS j
INNER JOIN [PreparedEmails] AS p
ON p.[PreparedEmailID] =
j.[PreparedEmailID]
and my generated linq query is like:
var query = from j in db.Jobs
join p in db.PreparedEmails on j.PreparedEmailID equals p.PreparedEmailID
join l in db.LoggedMessages on j.JobID equals l.JobID into ej
from l in ej.DefaultIfEmpty() orderby l.LoggedMessageID descending
orderby l.LoggedMessageID descending
orderby j.CreatedOn descending
select new
{
JobID = j.JobID,
PreparedEmailID = p.PreparedEmailID,
PreparedEmailName = p.Name,
CreatedOn = j.CreatedOn,
CompletedOn = j.CompletedOn,
SubscriberCount = j.SubscriberCount,
EmailsSent = j.EmailsSent,
LoggedMsg = l.Message
};
I prepared some linQ query for you (but i didn't test it in VS because i have no access to it now, so please be careful because it can contain some errors):
var list = from Jobs
join PreparedEmails on Jobs.PreparedEmailID == PreparedEmails.PreparedEmailID
join LoggedMessages on LoggedMessages.JobID == Jobs.JobID
select
{
JobID = Jobs.JobID,
PreparedEmailID = PreparedEmails.PreparedEmailID,
PreparedEmailName = PreparedEmails.Name,
CreatedOn= Jobs.CreatedOn,
CompletedOn = Jobs.CompletedOn,
SubscriberCount = Jobs.SubscriberCount,
EmailsSent = Jobs.EmailsSent,
LoggedMessage = LoggedMessages.Message
} orderby descending LoggedMessages.LoggedMessageID;
It should help a little bit ...
this is solution:
var query = from j in db.Jobs
join p in db.PreparedEmails on j.PreparedEmailID equals p.PreparedEmailID
orderby j.CreatedOn descending
select new
{
JobID = j.JobID,
PreparedEmailID = p.PreparedEmailID,
PreparedEmailName = p.Name,
CreatedOn = j.CreatedOn,
CompletedOn = j.CompletedOn,
SubscriberCount = j.SubscriberCount,
EmailsSent = j.EmailsSent,
LoggedMsg = (from l in db.LoggedMessages
where j.JobID == l.JobID
orderby l.LoggedMessageID descending
select l.Message).FirstOrDefault()
};

Left outer joins with 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
};

Mysql Join for 3 tables

I have checked former posts and none has solved my problem yet, any help would be appreciated
MYSQL query to 3 tables (Users, Match, Interview)
Want to return the users name and interview # (if there is an interview number) for the specified Match.
But I do not want to limit the results to only users who have an interview. I tried JOIN, but cannot get it to work for 3 tables.
Here is what I have so far in PHP:
$query = "SELECT CONCAT(u.first_name,' ',u.last_name,'----',COALESCE(i.v_code,'')) as name, u.id as id
FROM #__users as u
JOIN #__bl_match as m ON ( (u.team_id = m.team1_id) OR
(u.team_id = m.team2_id) OR
(u.team_id = m.team3_id AND m.team3_id != 0) OR
(u.team_id = m.team4_id AND m.team4_id != 0) OR
(u.team_id = m.team5_id AND m.team5_id != 0) OR
(u.team_id = m.team6_id AND m.team6_id != 0) OR
(u.team_id = m.team7_id AND m.team7_id != 0) OR
(u.team_id = m.team8_id AND m.team8_id != 0) OR
(u.team_id = m.team9_id AND m.team9_id != 0) OR
(u.team_id = m.team10_id AND m.team10_id != 0))
AND m.id = ".$t_id."AND m.id != 0
JOIN #__bl_interview as i ON i.u_id = u.id";
$db->setQuery($query);
$parti12 = $db->loadObjectList();
If you want Users with no Interview, you'll need to use a LEFT JOIN to the interview table, but that means the interview number for that user will be NULL.
Since you're concatenating the number with the user name in your SELECT list, this results in the user's name being returned as NULL when they've got no interviews (since concatenating a string with a NULL value - or performing pretty much any other operation on a NULL value - produces a NULL result).
To avoid this, you must handle the case when i.v_code is NULL. The typical way to do that in MySQL is with the COALESCE function:
SELECT CONCAT(u.first_name, ' ', u.last_name, '----', COALESCE(i.v_code,'')) as name,
u.id as id
FROM #__users as u
JOIN #__bl_match as m ON ( (u.team_id = m.team1_id) OR
(u.team_id = m.team2_id) OR
(u.team_id = m.team3_id AND m.team3_id != 0) OR
(u.team_id = m.team4_id AND m.team4_id != 0) OR
(u.team_id = m.team5_id AND m.team5_id != 0) OR
(u.team_id = m.team6_id AND m.team6_id != 0) OR
(u.team_id = m.team7_id AND m.team7_id != 0) OR
(u.team_id = m.team8_id AND m.team8_id != 0) OR
(u.team_id = m.team9_id AND m.team9_id != 0) OR
(u.team_id = m.team10_id AND m.team10_id != 0))
AND m.id = ".$t_id."AND m.id != 0
LEFT JOIN #__bl_interview as i ON i.u_id = u.id"
Now, given the formatting you're applying to the name, you may be left with an extraneous ---- after the name with no subsequent interview code. If you'd like to avoid that, we can use IF instead of COALESCE to get a little smarter with our output, like so:
SELECT CONCAT(u.first_name, ' ', u.last_name, IF(i.v_code, '---- ' + i.v_code, '')) as name
Note what that's doing: if i.v_code is not NULL, the first expression in the IF evaluates to true, so the second expression is returned. Otherwise, the third expression (the empty string) is returned - so when i.v_code is NULL, you only output the user's name.

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)

Full outer join - Linq To SQL

I'm trying to use Linq to SQL to do a full outer join. I had this working for a basic example, but it didn't work when each side of the full outer join were generated from another inner join. Below's the code. I realise that this could probably be put into less queries - but I'd rather split them out to make them as readable as possible. Performance isn't an issue in this case.
var productIds = db.OrderItemsIncoming.Select(i => i.ProductID)
.Union(db.OrderItemsOutgoing.Select(o => o.ProductID))
.Distinct();
var ordersIn = from o in db.OrdersIncoming
join i in db.OrderItemsIncoming on o.OrderNumber equals i.OrderNumber
select new { o, i };
var ordersOut = from o in db.OrdersOutgoing
join i in db.OrderItemsOutgoing on o.OrderNumber equals i.OrderNumber
select new { o, i };
var fullOuterJoinResults = from i in ordersIn
join o in ordersOut on i.i.ProductID equals o.i.ProductID into t
from o in t.DefaultIfEmpty()
where i == null ^ o == null
select new { i, o };
In my test, the ordersIn results is empty, and the ordersOut results has one row in it. So I want the final fullOuterJoinResults to have a row, but it's empty.
Literally a second after I post, I notice an error where I'm not using the productID results anywhere!!! :-/ I'll edit this post with my fix once I've got it working ...
[edit]
Okay, this seems to work:
var ordersIn = from o in db.OrdersIncoming
join i in db.OrderItemsIncoming on o.OrderNumber equals i.OrderNumber
select new { o, i };
var ordersOut = from o in db.OrdersOutgoing
join i in db.OrderItemsOutgoing on o.OrderNumber equals i.OrderNumber
select new { o, i };
var productIds = db.OrderItemsIncoming.Select(i => i.ProductID)
.Union(db.OrderItemsOutgoing.Select(o => o.ProductID))
.Distinct();
var fullOuterJoinResults = from pid in productIDs
join i in ordersIn on pid equals i.i.ProductID into t1
from i in t1.DefaultIfEmpty()
join o in ordersOut on pid equals o.i.ProductID into t2
from o in t2.DefaultIfEmpty()
where i == null ^ o == null
select new { i, o };