I'm struggling with what is a rather simple SQL select statement. How can this be translated into LINQ?
select
o.IdOrder, Date, s.suma, name, adresa
from
Clients c
join
Orders o on (c.IdClient = o.IdClient)
join
(select IdOrder, sum(price) suma
from OrderProduct
group by IdOrder) s on (o.IdOrder = s.IdOrder);
If you could point me in the right direction, I would greatly appreciate it.
This is what I have so far:
var y = from w in db.OrderProducts
group w by w.IdOrder into TotaledOrder
select new
{
IdOrder = TotaledOrder.Key,
price = TotaledOrder.Sum(s => s.price)
};
var i = 0;
var cc = new dynamic[100];
foreach (var item in y)
{
cc[i++] = db.Orders.Where(t => t.IdOrder == item.IdOrder)
.Select(p => new
{
IdOrder = item.IdOrder,
price = item.price,
}).Single();
}
Your SQL doesn't really give an idea on your underlying structure. By a guess on column names:
var result = from o in db.Orders
select new {
IDOrder = o.IDOrder,
Date = o.Date,
Suma = o.OrderProduct.Sum( op => op.Price),
Name = o.Client.Name,
Adresa = o.Client.Adresa
};
(I have no idea what you meant by the loop in your code.)
Related
I need to join two tables (Movimientos and Cuentas), group by CuentasId and make a SUM of Movimientos.Monto
Movimientos has a CuentasId to join this, and I can get the data from Cuentas but can not get the Sum.
This is my best approach, any help will be preciated, I'm a little confused with the syntax. Thanks in advance and kind regards,
var cuentas = (from mov in _data.Movimientos
join ct in _data.Cuentas
on mov.CuentasId equals ct.CuentasId
where ct.IsDeleted == 0 && mov.IsDeleted == 0
group ct by new
{
CuentasId = ct.CuentasId,
Alias = ct.Alias,
Moneda = ct.Monedas.Nombre,
Signo = ct.Monedas.Signo,
Banco = ct.Bancos.Nombre
} into ctg
select new
{
Alias = ctg.Key.Alias,
Moneda = ctg.Key.Moneda,
Signo = ctg.Key.Signo,
Banco = ctg.Key.Banco,
Monto = ctg.Sum(mov.Monto)
}
).ToList();
You need to group the value you want to sum like this
group mov.Monto by new { ..... } into ctg
Then ctg will be a collection of mov.Monto values grouped by your list of properties of ct and you'd just call Sum on ctg in your select
Monto = ctg.Sum()
So your new query would be
var cuentas = (from mov in _data.Movimientos
join ct in _data.Cuentas
on mov.CuentasId equals ct.CuentasId
where ct.IsDeleted == 0 && mov.IsDeleted == 0
group mov.Monto by new
{
CuentasId = ct.CuentasId,
Alias = ct.Alias,
Moneda = ct.Monedas.Nombre,
Signo = ct.Monedas.Signo,
Banco = ct.Bancos.Nombre
} into ctg
select new
{
Alias = ctg.Key.Alias,
Moneda = ctg.Key.Moneda,
Signo = ctg.Key.Signo,
Banco = ctg.Key.Banco,
Monto = ctg.Sum()
}).ToList();
You could also try grouping by first and then just summing the items later:
var cuentas = (from mov in _data.Movimientos.Where(w => w.IsDeleted == 0).GroupBy(g => g.CuentasId)
join ct in _data.Cuentas.Where(w => w.IsDeleted == 0).GroupBy(g => new { CuentasId = g.CuentasId, Alias = g.Alias, Monedas = g.Monedas.Nombre, Signo = g.Monedas.Signo, Banco = g.Bancos.Nombre })
on mov.Key.CuentasId equals ct.Key.CuentasId
select new
{
Alias = ct.Key.Alias,
Moneda = ct.Key.Moneda,
Signo = ct.Key.Signo,
Banco = ct.Key.Banco,
Monto = mov.Sum(s => s.Monto)
}
).ToList();
Actually I want to return the data from different lists based on Date. When i'm using this i'm getting data upto #Var result but i'm unnable to return the data. The issue with this is i'm getting error #return result. I want to return the data #return result. I'm using Linq C#. Can anyone help me out?
public List<CustomerWiseMonthlySalesReportDetails> GetAllCustomerWiseMonthlySalesReportCustomer()
{
var cbsalesreeport = (from cb in db.cashbilldescriptions
join c in db.cashbills on cb.CashbillId equals c.CashbillId
join p in db.products on cb.ProductId equals p.ProductId
select new
{
Productamount = cb.Productamount,
ProductName = p.ProductDescription,
CashbillDate = c.Date
}).AsEnumerable().Select(x => new ASZ.AmoghGases.Model.CustomerWiseMonthlySalesReportDetails
{
Productdescription = x.ProductName,
Alldates = x.CashbillDate,
TotalAmount = x.Productamount
}).ToList();
var invsalesreeport = (from inv in db.invoices
join invd in db.invoicedeliverychallans on inv.InvoiceId equals invd.InvoiceId
select new
{
Productamount = invd.Total,
ProductName = invd.Productdescription,
InvoiceDate = inv.Date
}).AsEnumerable().Select(x => new ASZ.AmoghGases.Model.CustomerWiseMonthlySalesReportDetails
{
Productdescription = x.ProductName,
Alldates = x.InvoiceDate,
TotalAmount = x.Productamount
}).ToList();
var abc = cbsalesreeport.Union(invsalesreeport).ToList();
var result = (from i in abc
group i by new { Date = i.Alldates.ToString("MMM"), Product = i.Productdescription } into grp
select new { Month = grp.Key, Total = grp.Sum(i => i.TotalAmount) });
**return result;**
}
You can either convert your result to a List before returning it using return result.ToList() or make your method return an IEnumerable<CustomerWiseMonthlySalesReportDetails> instead of List.
As your result is an enumeration of anonymous types you have to convert them to your CustomerWiseMonthlySalesReportDetails-type first:
select new CustomerWiseMonthlySalesReportDetails{ Month = grp.Key, Total = grp.Sum(i => i.TotalAmount) });
Assuming your type has exactly the members returned by the select.
EDIT: So your code should look like this:
var result = (from i in abc
group i by new { Date = i.Alldates.ToString("MMM"), Product = i.Productdescription } into grp
select new CustomerWiseMonthlySalesReportDetails{ Month = grp.Key, Total = grp.Sum(i => i.TotalAmount) });
return result.ToList();
You can assume Alldates property if is date of one of groups that month of date is in right place:
var result = (from i in abc
group i by new { Date = i.Alldates.ToString("MMM"), Product = i.Productdescription }
into grp
select new CustomerWiseMonthlySalesReportDetails{
Productdescription = grp.Key.Product,
TotalAmount = grp.Sum(i => i.TotalAmount),
Alldates =grp.First(i=>i.Alldates ) })
.ToList();
I have the following SQL that I would like to write as a single linq statement:
SELECT
P.PartyId,
P.PartyDate,
SUM(COALESCE(R.PaidAmount, 0)) AS AmountPaid
FROM
Party AS P
LEFT JOIN Reservation as R
ON P.PartyID = R.PartyID
GROUP BY P.PartyID, P.PartyDate
ORDER BY P.PartyDate DESC
The best I can do is use two sets of linq queries, like so:
var localList = from partyList in localDb.Parties
join reservationList in localDb.Reservations on
partyList.PartyID equals reservationList.PartyID into comboList
from newList in comboList.DefaultIfEmpty()
select new PartyAmounts {
PartyID = partyList.PartyID,
PartyDate = partyList.PartyDate,
AmountPaid = (newList.PaidAmount ?? 0) };
var secondList = from groupList in localList
group groupList by new {
groupList.PartyID,
groupList.PartyDate} into resList
select new PartyAmounts {
PartyID = resList.Key.PartyID,
PartyDate=resList.Key.PartyDate,
AmountPaid = resList.Sum(x => x.AmountPaid)};
I don't care if it's a method chain or a lambda but I would love to know how this is supposed to go together. I can only barely understand the two I've got now.
Thanks for the help.
var list = from partyList in localDb.Parties
join reservationList in localDb.Reservations on partyList.PartyID equals reservationList.PartyID into comboList
from details in comboList.DefaultIfEmpty() // Left join
group details by new {partyList.PartyID, partyList.PartyDate} into grouped // So that the group have both keys and all items in details
select new PartyAmounts
{
PartyID = grouped.Key.PartyID,
PartyDate = grouped.Key.PartyDate,
AmountPaid = grouped.Sum(x => x.AmountPaid ?? 0)}
};
I am trying to sort a listbox by the customerID and then by Total (discount*unitPrice*quantity) and cannot manage to organize the code in a way that will sort it in that way. Any help would be greatly appreciated.
HERE is a link showing an image on how the results should be returned as.
var load1 = System.IO.File.ReadAllLines(#"c:\temp\AS3Products.csv")
.Select(x => new
{
CID = x.Split(',')[0],
discount = x.Split(',')[2].Trim(),
productId = x.Split(',')[0].Trim()
});
var load2 = System.IO.File.ReadAllLines(#"c:\temp\AS3Transactions.csv")
.Select(x => new
{
productId = x.Split(',')[3],
unitPrice = x.Split(',')[4],
quantity = x.Split(',')[5]
});
var querypractice = from x in load1
join y in load2 on x.productId equals y.productId
where x.CID == "110"
orderby x.discount, y.quantity
select new { x.CID, x.discount, x.productId, y.quantity, y.unitPrice };
foreach (var x in querypractice)
{
double total = double.Parse(x.quantity) * double.Parse(x.unitPrice) * double.Parse(x.discount);
listBox1.Items.Add(x.CID+ " " +x.discount+" "+x.quantity+ " " + total);
}
Disclaimer: I don't have VS on this machine, so this isn't validated, but I think you can do it using the LET statement to set up the calculated value, then order based on it.
var querypractice = from x in load1
join y in load2 on x.productId equals y.productId
let total = x.discount*x.unitPrice*x.quantity
where x.CID == "110"
orderby x.CID, total
select new { x.CID, total };
http://www.codeproject.com/Articles/231164/Into-and-let-in-LINQ-Let-vs-Into
If you're positive that these files have numbers in the expected places all the time, you could parse them as you read them from the files. Otherwise, you'll want to do some validation first or you'll get exceptions.
(I changed double.Parse to decimal.Parse - it's more accurate for manipulating dollar amounts.)
var load1 = System.IO.File.ReadAllLines(#"c:\temp\AS3Products.csv")
.Select(x => new
{
CID = int.Parse(x.Split(',')[0]),
discount = decimal.Parse(x.Split(',')[2].Trim()),
productId = int.Parse(x.Split(',')[0].Trim())
});
var load2 = System.IO.File.ReadAllLines(#"c:\temp\AS3Transactions.csv")
.Select(x => new
{
productId = int.Parse(x.Split(',')[3]),
unitPrice = decimal.Parse(x.Split(',')[4]),
quantity = int.Parse(x.Split(',')[5])
});
Then you can create your list like this. (I removed the specific id you had in your query.)
var orderedList = (from x in load1
join y in load2 on x.productId equals y.productId
let total = (x.discount * y.unitPrice * y.quantity)
orderby x.CID descending, total descending
select new
{
x.CID,
x.discount,
x.productId,
y.quantity,
y.unitPrice
});
I have a long list with ships that I get from a Linq to SQL query, but I only want one row per ImoNo. Today i have about 4 rows per ImoNo. I just need the one row that has been last updated (so in this example I need 2013-01-27).
This is my Linq To SQL query:
var res = from positions in context.Lloyds_ETAs
join vessels in context.Lloyds_Vessels on positions.ImoNumber equals vessels.imo_no
select new PositionData {
ImoNo = positions.ImoNumber,
PositionCordinates = positions.AIS_Latest_Position,
CompassOverGround = positions.Compass_over_Ground_Heading,
VesselId = positions.Vessel_ID,
Equipment = vessels.vessel_type,
Updated = positions.Last_Place_Location
};
return res.ToList();
var res = (from positions in context.Lloyds_ETAs
join vessels in context.Lloyds_Vessels on positions.ImoNumber equals vessels.imo_no
select new PositionData {
ImoNo = positions.ImoNumber,
PositionCordinates = positions.AIS_Latest_Position,
CompassOverGround = positions.Compass_over_Ground_Heading,
VesselId = positions.Vessel_ID,
Equipment = vessels.vessel_type,
Updated = positions.Last_Place_Location
})
.GroupBy(x => x.ImoNo)
.Select(g => g.OrderByDescending(pd => pd.Updated).First());
If you want the last one, all you have to do is append .OrderBy(pd => pd.Updated).Last() after your select.
var res = (from positions in context.Lloyds_ETAs
join vessels in context.Lloyds_Vessels on positions.ImoNumber equals vessels.imo_no
select new PositionData {
ImoNo = positions.ImoNumber,
PositionCordinates = positions.AIS_Latest_Position,
CompassOverGround = positions.Compass_over_Ground_Heading,
VesselId = positions.Vessel_ID,
Equipment = vessels.vessel_type,
Updated = positions.Last_Place_Location
}).OrderBy(pd => pd.Updated).Last();
return res.ToList();
(yourQuery).OrderByDescending(pd=>pd.Updated).First()
There are several ways to get just one "row" as a result:
res.OrderByDescending(x => x.Updated).Take(1);
res.OrderByDescending(x => x.Updated).First();
res.Order(x => x.Updated).Last();
It seems that you have some duplication though, so maybe doing a group by would be more appropriate.