Converting Oracle SQL query with left outer join to Linq - linq

I'm trying to convert the Oracle Sql query below to linq, without much success. I'm not sure how to handle the line AND ShipSeq = i.ShipSeq(+), which I've learned is a LEFT OUTER JOIN in Oracle. I'm testing the Linq query below in LinqPad, where I don't get any syntax errors but it errors on executing the query. Any ideas?
Oracle Sql Query
SELECT *
FROM CustomerShip,
(SELECT DISTINCT b.ShipSeq AS shipSeq
FROM Orders a,
CustomerShip b
WHERE a.OrderId IN (SELECT OrderId
FROM Orders
WHERE CustomerId = #CustomerId
AND OrderType <> 'A')
AND b.CustomerId = #CustomerId
AND b.ShipSeq = a.CustShip
AND OrderStatus <> 'C'
GROUP BY b.ShipSeq) i
WHERE CustomerId = #CustomerId
AND (Address NOT LIKE '%RETAIL%STORE%')
AND ShipSeq = i.ShipSeq(+)
ORDER BY ShipTo DESC, OrderDate DESC;
Linq Query
var query = from s in CustomerShip
join m in Orders on s.ShipTo equals m.ShipTo into temp
from x in temp.DefaultIfEmpty()
where (from o in Orders
from c in CustomerShip
where (from x in CustomerOrders
where x.CustomerId == customerId
&& !x.OrderType.Equals("A")
select x.OrderId).Contains(o.OrderId)
&& c.CustomerId == customerId
&& c.ShipTo == o.ShipTo
&& !o.OrderStatus.Equals("C")
select c.ShipTo).Distinct().Contains(s.ShipTo)
&& s.CustomerId == customerId
&& !s.Address.Contains("RETAIL")
&& !s.Address.Contains("STORE")
orderby s.ShipTo descending, s.OrderDate descending
select s;

I think a literal translation looks like this:
var iQuerySub = from o in Orders where o.CustomerId == pCustomerId && o.OrderType != "A" select o.OrderId;
var iQuery = (from a in Orders
from b in CustomerShip
where iQuerySub.Contains(a.OrderId) &&
b.CustomerId == pCustomerId &&
b.ShipSeq == a.CustShip &&
a.OrderStatus != "C"
group b by b.ShipSeq into bg
select new { shipSeq = bg.Key }).Distinct();
var ans = from s in CustomerShip
where s.CustomerId == pCustomerId &&
(!s.Address.Contains("RETAIL") || !s.Address.Contains("STORE") || s.Address.IndexOf("RETAIL") > s.Address.IndexOf("STORE"))
join i in iQuery on s.ShipSeq equals i.shipSeq into ij
from i in ij.DefaultIfEmpty()
orderby s.ShipTo, s.OrderDate descending
select new { s, shipSeq = (i != null ? i.shipSeq : (int?)null) };
But both the SQL and LINQ seem inefficient to me, but without domain knowledge this is all I could optimize:
var iQuery2 = (from b in CustomerShip
where b.CustomerId == pCustomerId &&
Orders.Any(a => a.CustomerId == pCustomerId && a.OrderType != "A" && a.OrderStatus != "C" && b.ShipSeq == a.CustShip)
select new { shipSeq = b.ShipSeq }).Distinct();
var ans2 = from s in CustomerShip
where s.CustomerId == pCustomerId &&
(!s.Address.Contains("RETAIL") || !s.Address.Contains("STORE") || s.Address.IndexOf("RETAIL") > s.Address.IndexOf("STORE"))
join i in iQuery2 on s.ShipSeq equals i.shipSeq into ij
from i in ij.DefaultIfEmpty()
orderby s.ShipTo, s.OrderDate descending
select new { s, shipSeq = (i != null ? i.shipSeq : (int?)null) };

Related

Get "group by" data other than the Key element

I'm trying to get the sum of fees per customer per month from the mysql sakila database.
My SQL query looks like this:
select first_name, last_name, MONTHNAME(payment_date) as Month, sum(amount) as FeeSum
from customer c
join payment p on c.customer_id = p.customer_id
where (payment_date between '2005-01-01' AND '2005-06-30')
group by c.customer_id, Month
order by Month desc, FeeSum desc;
I did this in linqpad
var q11 = from c in Customer
from p in Payment
where c.Customer_id == p.Customer_id && ((DateTime)p.Payment_date) > DateTime.Parse("2005-01-01") && ((DateTime)p.Payment_date) < DateTime.Parse("2005-06-30")
group new {c, p} by new {((DateTime)p.Payment_date).Month, p.Customer_id} into grp
select new {
Month = grp.Key.Month,
FeeSum = grp.Sum(s => s.p.Amount),
} into selection
orderby selection.Month, selection.FeeSum descending
select selection;
q11.Dump();
Which works for the FeeSum and the Month, but I can't figure out how to get the first_name and the lasT_name of the customer
Since the members of each grp all have the same Customer, just pick any one:
var q11 = from c in Customer
from p in Payment
where c.Customer_id == p.Customer_id && ((DateTime)p.Payment_date) > DateTime.Parse("2005-01-01") && ((DateTime)p.Payment_date) < DateTime.Parse("2005-06-30")
group new { c, p } by new { ((DateTime)p.Payment_date).Month, p.Customer_id } into grp
select new {
grp.First().first_name,
grp.First().last_name,
Month = grp.Key.Month,
FeeSum = grp.Sum(s => s.p.Amount),
} into selection
orderby selection.Month, selection.FeeSum descending
select selection;
Note: I prefer to use let rather than select twice, but it is the same thing internally, I believe:
var q11 = from c in Customer
from p in Payment
where c.Customer_id == p.Customer_id && ((DateTime)p.Payment_date) > DateTime.Parse("2005-01-01") && ((DateTime)p.Payment_date) < DateTime.Parse("2005-06-30")
group new { c, p } by new { ((DateTime)p.Payment_date).Month, p.Customer_id } into grp
let FeeSum = grp.Sum(s => s.p.Amount)
orderby grp.Key.Month, FeeSum descending
select new {
grp.First().first_name,
grp.First().last_name,
Month = grp.Key.Month,
FeeSum
};

Convert this sql command to c# linq

I am trying to convert this tSql command to linq query.
I want to group this columns.
Can you help me?
select vUnit.FK_Unit_ID , Unit.unitNumber, unit.unitTitle , title.featureTitleName
from unit.UnitFeatureValue vUnit
inner join unit.Unit on vUnit.FK_Unit_ID = Unit.ID
inner join unit.FeatureTitle title on vUnit.FK_FeatureTitle_ID = title.ID
where vUnit.FK_Unit_ID = 15 and title.canMoreSelect = 1
group by vUnit.FK_Unit_ID ,unit.unitNumber, unit.unitTitle , title.featureTitleName
var query = (
from v in dbContext.UnitFeatureValue
join u in dbContext.Unit on v.FK_Unit_ID equals u.ID
join t in dbContext.FeatureTitle on v.FK_FeatureTitle_ID equals t.ID
where v.FK_Unit_ID == 15 && t.canMoreSelect == 1
select new {
v.FK_Unit_ID,
u.unitNumber,
u.unitTitle,
t.featureTitleName,
}).Distinct();
something like this
var result = (from v in vUnit
join u in unit on v.FK_Unit_ID equals u.ID
join t in title on v.FK_FeatureTitle_ID equals t.ID
where v.FK_Unit_ID == 15 and t.canMoreSelect == 1
select new { v.FK_Unit_ID , u.unitNumber, u.unitTitle , t.featureTitleName }).ToList();

How do I convert this query into LINQ?

SELECT *
FROM
ProcedureLookup ProcLookup
INNER JOIN (SELECT PatientProcedures.PP_ProcedureId, COUNT(*) as ProcCount
FROM (PatientProcedures INNER JOIN Treatments ON PatientProcedures.PP_TreatmentId = Treatments.TS_TreatmentId)
WHERE YEAR(Treatments.TS_Date) = YEAR(GETDATE())
GROUP BY PatientProcedures.PP_ProcedureId) cyearProc ON ProcLookup.PL_ProcedureId = cyearProc.PP_ProcedureId
ORDER BY ProcCount DESC;
Here ProcedureLookup, Treatments, PatientProcedures are the tables.
Here linq query.
var result = (from ProcLookup in db.ProcedureLookup
join cyearProc in (
from p in db.PatientProcedures
join t in db.Treatments on p.PP_TreatmentId equals
t.TS_TreatmentId
where
t.TS_Date.Year == DateTime.Now.Year
group p by p.PP_ProcedureId into g
select new
{
PP_ProcedureId = g.Key,
ProcCount = g.Count()
}
) on ProcLookup.PL_ProcedureId equals
cyearProc.PP_ProcedureId
orderby cyearProc.ProcCount descending
select new
{
// Columns
PP_ProcedureId = ProcLookup.PP_ProcedureId,
ProcCount = cyearProc.ProcCount
}).ToList();

Why my Linq query gives wrong results

I have this SQL query which gives the output as 15.but, when I converted the same query in Linq,it gives an output as 72.
select sum(DATEDIFF(day,LeaveBreakup.StartDate,LeaveBreakup.EndDate)+1) as totalNoOfDays from LeaveApplication
inner join Employee
on LeaveApplication.Employee=Employee.Id
inner join Team
on Employee.Team=Team.Id
inner join LeaveBreakup
on LeaveApplication.Id=LeaveBreakup.LeaveApplication
inner join LeaveTypeDetail
on LeaveBreakup.LeaveType=LeaveTypeDetail.LeaveType
where Employee.Team=5 and LeaveStatus!=0 and LeaveBreakup.StartDate between '01-01-2016' and '01-31-2016' and LeaveBreakup.WhichHalf=0
var Stafflist = (from LApp in db.LeaveApplications
join Emp in db.Employees
on LApp.Employee equals Emp.Id
join Tm in db.Teams
on Emp.Team equals Tm.Id
join LBrk in db.LeaveBreakups
on LApp.Id equals LBrk.LeaveApplication
join LTD in db.LeaveTypeDetails
on LBrk.LeaveType equals LTD.LeaveType
where Emp.Team == 5 && LApp.LeaveStatus != 0 && LBrk.StartDate >= d1 && LBrk.StartDate <= d2 && LBrk.WhichHalf == 0
select DbFunctions.DiffMinutes(LBrk.StartDate, LBrk.EndDate)).Sum() / 60;

join on subquery results

I've got a table called IssueStatuses and another table called Issues. Issues has a StatusID and SubStatusID, both of which are from the IssueStatuses table which has an additional field that states if it's a SubStatus or not, like so:
IssueStatuses
IssueStatusID
IssueStatus
IsSubStatus
I'm trying to get a list of SubStatuses for a particular list of Issues. In SQL it's:
SELECT iss.IssueStatus, COUNT(iss.IssueStatus) AS Total
FROM Issues AS Issues
INNER JOIN Rooms r ON Issues.RoomID = r.RoomID
INNER JOIN Locations l ON l.LocationID = r.LocationID
INNER JOIN Customers c ON l.CustomerID = c.CustomerID
INNER JOIN (SELECT * FROM IssueStatuses WHERE IsSubStatus = 0) ist ON Issues.IssueStatusID = ist.IssueStatusID
INNER JOIN (SELECT * FROM IssueStatuses WHERE IsSubStatus = 1) iss ON Issues.IssueSubStatusID = iss.IssueStatusID
WHERE c.Customer = 'ABC'
AND l.Location = 'MySite'
GROUP BY iss.IssueStatus
but I"m having trouble converting it to LINQ. The desired output would be something like:
IssueStatus | Total
-------------------
Open 15
Delayed 25
On Time 8
Here's what I've tried with LINQ:
var query = from i in Issues
join r in Rooms on i.RoomID equals r.RoomID
join l in Locations on r.RoomID equals l.LocationID
join c in Customers on l.CustomerID equals c.CustomerID
where i.IssueStatusID == (from ist in IssueStatuses
where ist.IsSubStatus == false
select ist)
&& i.IssueSubStatusID == (from iss in IssueStatuses
where iss.IsSubStatus == true
select iss)
&& c.Custome == "ABC"
&& l.Location == "MySite"
group i by i.IssueStatus
but I know it's wrong because LINQPad throws an error stating:
can't convert int to type Models.IssueStatus
What I need to do is use iss.IssueStaus to group on but I can't access it. Can someone tell me what I'm doing wrong?
How about this (untested but I should be close):
var query = from i in Issues
join r in Rooms on i.RoomID equals r.RoomID
join l in Locations on r.LocationID equals l.LocationID
join c in Customers on l.CustomerID equals c.CustomerID
join ist in IssueStatuses on i.IssueStatusID equals ist.IssueStatusID
join iss in IssueStatuses on i.IssueSubStatusID equals iss.IssueStatusID
where !ist.IsSubStatus && iss.IsSubStatus
&& c.Customer == "ABC"
&& l.Location == "MySite"
group i by iss.IssueStatus into g
select new {IssueStatus = g.Key, Total = g.Count()}
Your two inner from statements return objects and not IDs ... select the ID you need like ist.IssueStatusID:
var query = from i in Issues
join r in Rooms on i.RoomID equals r.RoomID
join l in Locations on r.RoomID equals l.LocationID
join c in Customers on l.CustomerID equals c.CustomerID
where (from ist in IssueStatuses
where ist.IsSubStatus == false
select ist.IssueStatusID).Contains(i.IssusStatusID)
&& (from iss in IssueStatuses
where iss.IsSubStatus == true
select iss.IssueStatusID).Contains(i.IssueSubStatusID)
&& c.Customer == "ABC"
&& l.Location == "MySite"
group i by i.IssueStatus

Resources