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
};
Related
I have to join outer table column with inner table minimum value column
Here is my sql query:
SELECT O.Id, O.Name, O.Designation
FROM TableA AS O INNER JOIN
(SELECT MIN(SrNo) AS A_SNo, Id
FROM TableA
WHERE (Active = 1)
GROUP BY Id) AS I ON O.Id = I.Id AND O.SrNo = I.A_SNo AND O.Active = 1
I have tried this:
from tres in TableA join O in
(from tresp in TableA
where tresp.Active == true
group tresp by new { tresp.Id } into G
select new { Id = G.Key.Id, A_Sno =(int?)G.Min(X=>X.SrNo)}
) on new {tres.Id,a=(int?)tres.SrNo } equals new {O.Id,a=O.A_Sno } into tresss
where (tres.Active==true)
select new { tres.Id, tres.Name, tres.Designation }
in sql query I'm not getting duplicate rows but when i tried this in linq getting duplicate rows
try
from tres in TableA join O in
(from tresp in TableA
where tresp.Active == true
group tresp by new { tresp.Id } into G
select new { Id = G.Key.Id, A_Sno =(int?)G.Min(X=>X.SrNo)}
) on new {tres.Id,a=(int?)tres.SrNo } equals new {O.Id,a=O.A_Sno }
where (tres.Active==true)
select new {tres.Id,tres.Name,tres.Designation} into tresss
select new { tresss.Id, tresss.Name, tresss.Designation }
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) };
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();
SELECT TOP (5)
Sales.Product, Sales.Product_Price, COUNT(*) AS CNT,
Products.Category, Products.IMG_URL, Products.Rate_Avg
FROM
Sales
INNER JOIN
Products ON Sales.Product = Products.Product
GROUP BY
Sales.Product, Sales.Product_Price,
Products.Category, Products.IMG_URL, Products.Rate_Avg
HAVING
(COUNT(*) > 1)
ORDER BY CNT DESC
Most of that query has a 1-to-1 correspondence to the equivalent linq-to-sql expression. Though the TOP (5) part needs to be added to the end.
(from s in db.Sales
join p in db.Products on s.Product equals p.Product
group s by new { s.Product, s.Product_Price, p.Category, p.IMG_URL, p.Rate_Avg } into g
where g.Count() > 1
orderby g.Count() descending
select new
{
g.Key.Product,
g.Key.Product_Price,
CNT = g.Count(),
g.Key.Category,
g.Key.IMG_URL,
g.Key.Rate_Avg,
}).Take(5)
I've got a problem in getting my groupby's right in a Linq to SQL query.
I have 3 tables: Customers, Orders and OrderItems. The OrderItems contain the quantity and price of the items purchased.
Now I simply would like to list all the customers with the total price of all orders.
I have (amongst a number of other tries) this, but it's not compiling. There is no TotalPrice item in the Intellisense where I have the ??? in the last line.
var q = (from c in db.Customers
join o in db.Orders on c.ID equals o.Customer
//join oi in db.OrderItems on o.ID equals oi.OrderID
group c by new {c.CustomerName, TotalPrice = o.OrderItems.Sum(x => x.Quantity * x.Price)} into groupby
select groupby);
foreach (var cust in q)
Console.WriteLine("{0} {1}", cust.Min(x => x.CustomerName), cust.Sum(x => x.???);
The (easy, understandable, straight forward and simple) SQL query will look like this:
SELECT C.ID, MIN(CustomerName) CustomerName, SUM(Quantity * Price) OrderPrice
FROM Customers C
INNER JOIN ORDERS O ON C.ID = O.Customer
INNER JOIN OrderItems OI ON O.ID = OI.OrderID
GROUP BY C.ID
This works for me:
This is sums by Customer and Order
var orders = (from c in context.Customers
join o in context.Orders on c.custid equals o.custid
join od in context.OrderDetails on o.orderid equals od.orderid
select new
{
c.custid,
o.orderid,
od.qty,
od.unitprice
}).GroupBy(c => new
{
c.custid,
c.orderid
}).Select(c => new
{
c.Key.custid,
c.Key.orderid,
Summ = c.Sum(d => d.qty * d.unitprice)
}).ToList();
This is sums by Customer only
var orders = (from c in context.Customers
join o in context.Orders on c.custid equals o.custid
join od in context.OrderDetails on o.orderid equals od.orderid
select new
{
c.custid,
od.qty,
od.unitprice
}
).GroupBy(c => new
{
c.custid,
}).Select(c => new
{
c.Key.custid,
Summ = c.Sum(d => d.qty * d.unitprice)
}).ToList();
I can mess with names, but here is LinQ expression with Extension methods syntax that match your SQL:
var q = db.Customers
.GroupBy(x => new
{
x.ID,
x.CustomerName,
}, (x, group) => new
{
Id = x.ID,
CustomerName = x.CustomerName,
TotalPrice = group.Select(y => y.Orders.Sum(z => z.OrderItems.Sum(a => a.Price * a.Quantity)))
});
foreach (var cust in q)
Console.WriteLine("{0} {1}", cust.CustomerName, cust.TotalPrice);
This is also working for me:
var q = (from c in db.Customers
join o in db.Orders on c.ID equals o.Customer
join oi in db.OrderItems on o.ID equals oi.OrderID
group new {c, o.ID, oi.Quantity, oi.Price} by new {c.ID, c.CustomerName} into grp
let TotalPrice = grp.Sum(x => x.Quantity * x.Price)
select new
{
CustomerID = grp.Key.ID,
CustomerName = grp.Key.CustomerName,
TotalPrice
});
and
var q = (from c in db.Customers
join o in db.Orders on c.ID equals o.Customer
join oi in db.OrderItems on o.ID equals oi.OrderID
group new { CustomerID = c.ID, CustomerName = c.CustomerName, Price = oi.Price, Quantity = oi.Quantity} by c.ID into grp
select new
{
ID = grp.Key,
CustomerName = grp.Min(x => x.CustomerName),
TotalPrice = grp.Sum(x => x.Price * x.Quantity)
});