This question already has answers here:
DISTINCT() and ORDERBY issue
(4 answers)
Closed 2 years ago.
I am selecting from a table using LINQ.
I want to order by the sum of two columns.
Here is a simplified version of what isn't working for me
List<DTO.Test> rtn = (from i in db.Table1
orderby i.col1 + i.col2 descending
select i).Take(200).ToList();
****** Edit - this is the full code
List<DTO.Investigation> rtn = (from i in db.Investigations
where i.IsDeleted == false
orderby i.total + i.prevtotal descending
select new DTO.Investigation()
{
InvestigationID = i.InvestigationID,
InvestigationDate = i.InvestigationDate.Value,
}).Distinct().Take(200).ToList();
Your original question had orderby col1 + col2 descending, but the correct syntax for orderby is:
orderby i.col1 + i.col2 descending
Make sure you have using System.Linq near the top of the file.
A fully working solution:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static ApplicationDbContext db = new ApplicationDbContext();
static void Main(string[] args)
{
if (!db.People.Any())
{
db.People.Add(new Person { Name = "John", Score1 = 5, Score2 = 1 });
db.People.Add(new Person { Name = "Mary", Score1 = 2, Score2 = 5 });
db.SaveChanges();
}
// Query Syntax
List<PersonDto> results = (from p in db.People
orderby p.Score1 + p.Score2 descending
select new PersonDto { Id = p.Id, Name = p.Name, TotalScore = p.Score1 + p.Score2 })
.Take(200)
.ToList();
// Method Syntax
List<PersonDto> results2 = db.People
.OrderByDescending(p => p.Score1 + p.Score2)
.Select(p => new PersonDto { Id = p.Id, Name = p.Name, TotalScore = p.Score1 + p.Score2 })
.Take(200)
.ToList();
Console.WriteLine("{0,-5}{1,-10}{2,-10}", "Id", "Name", "TotalScore");
foreach (var item in results1)
{
Console.WriteLine("{0,-5}{1,-10}{2,-10}", item.Id, item.Name, item.TotalScore);
}
Console.ReadKey();
}
}
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext() : base(#"Data Source=(localdb)\MSSQLLocalDB; Initial Catalog=Db63409328; Integrated Security=true")
{
}
public DbSet<Person> People { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Score1 { get; set; }
public int Score2 { get; set; }
}
public class PersonDto
{
public int Id { get; set; }
public string Name { get; set; }
public int TotalScore { get; set; }
}
}
Related
I need to translate the following SQLite query to LINQ in C#
SELECT sup.SupplierName, sup.SupplierID, pr.Price, max(pr.AddedDate)
FROM Suppliers sup
LEFT JOIN ItemsPrices pr
USING(SupplierID)
WHERE pr.ItemID = '22'
GROUP BY sup.SupplierName
I've searched about all web site and tried the following LINQ query and it does group like what I want but doesn't select latest date. I'm newbie in LINQ please help me
internal List<LatestPriceDbo> GetLatestPrice(int _itemid)
{
using (dbContext context = new dbContext())
{
var groupedPrice = from a in context.ItemsPrices
where a.ItemId == _itemid
orderby a.Id descending
group a by new { a.ItemId, a.SupplierId } into g
select new ItemsPrice
{
SupplierId = g.Key.SupplierId,
ItemId = g.Key.ItemId,
Price = g.FirstOrDefault().Price,
AddedDate = g.Max(s => s.AddedDate)
};
var result = (from c in context.Suppliers
from k in groupedPrice
where k.ItemId == _itemid && c.SupplierId == k.SupplierId
select new LatestPriceDbo
{
supid = c.SupplierId,
supname = c.SupplierName,
price = k.Price,
addeddate = k.AddedDate
}).ToList();
return result;
}
}
internal class LatestPriceDbo
{
public int supid { get; set; }
public string supname { get; set; }
public decimal price { get; set; }
public string addeddate { get; set; }
}
I am using Database-First.
You should be able to use a LINQ Join I have mocked up something which might point you in the correct direction:
Notes
use the join first to get the set you looking for
you can then do a nested select for the max based on supplierId.
from a in context.ItemsPrices
join s in context.Suppliers on a.SupplierId equals s.supplierId
where a.ItemId == _itemid
orderby a.Id descending
select new ItemsPrice
{
SupplierName = s.SupplierName
SupplierId = a.SupplierId,
ItemId = a.ItemId,
Price = a.FirstOrDefault().Price,
AddedDate = context.ItemsPrices.Where(x => x.SupplierId == a.SupplierId).Max(s => s.AddedDate)
};
I solved the problem owing to Kevin's suggestion. I did need to be more search on web to improve the code block of Kevin's comment and I did.
internal List<LatestPriceDbo> GetLatestPrice(int _itemid)
{
using (dbContext context = new dbContext())
{
var result = (from a in context.ItemsPrices
join s in context.Suppliers on a.SupplierId equals s.SupplierId
where a.ItemId == _itemid
orderby a.Id descending
group new { a, s } by new { a.SupplierId, a.ItemId } into grb
select new LatestPriceDbo
{
supname = grb.FirstOrDefault().s.SupplierName,
supid = grb.Key.SupplierId,
itemid = grb.Key.ItemId,
price = context.ItemsPrices
.Where(x => x.ItemId == grb.FirstOrDefault().a.ItemId)
.OrderByDescending(z => z.Id).Select(z => z.Price)
.FirstOrDefault(),
addeddate = context.ItemsPrices
.Where(x => x.SupplierId == grb.FirstOrDefault().a.SupplierId)
.Max(s => s.AddedDate)
}).ToList();
return result;
}
}
internal class LatestPriceDbo
{
public int itemid { get; set; }
public int supid { get; set; }
public string supname { get; set; }
public decimal price { get; set; }
public string addeddate { get; set; }
public int recordid { get; set; }
}
I am trying to convert the following SQL using LINQ in c#
enter code here
SELECT t2.AccountID, t1.Name, t1.ParentID, SUM(t2.Debit), SUM(t2.Credit)
FROM t2.INNER JOIN
t1.ON t2.AccountID = t1.ID
GROUP BY t2.AccountID, t2.Name, t1.ParentID
HAVING (t1.ParentID = 22)
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication23
{
class Program
{
static void Main(string[] args)
{
Name[] names = null;
Amount[] amounts = null;
var results = (from t1 in names.Where(x => x.ParentID == 22)
join t2 in amounts on t1.ID equals t2.AccountID
select new { t1 = t1, t2 = t2 }
)
.GroupBy(x => new { accountId = x.t2.AccountID, name = x.t1.Name, parent = x.t1.ParentID })
.Select(x => new { accountID = x.Key.accountId, name = x.Key.name, parentID = x.Key.parent, debit = x.Sum(y => y.t2.Debit), credit = x.Sum(y => y.t2.Credit) })
.ToList();
}
}
public class Name
{
public int ParentID { get; set; }
public string Name { get; set; }
public int ID { get; set; }
}
public class Amount
{
public int AccountID { get; set; }
public decimal Debit { get; set; }
public decimal Credit { get; set; }
}
}
I am working to convert the below SQL code to LINQ query for MVC. It got multiple nested joins and group by.
SELECT UnitTracts.Id,
UnitTracts.UnitId,
Leases.Id,
Leases.Lessor,
Leases.Lessee,
Leases.Alias,
Leases.LeaseDate,
Leases.GrossAcres,
IIf([Page] Is Null,[VolumeDocumentNumber],[VolumeDocumentNumber] + '/' + [Page]) AS [Vol/Pg],
Leases.Legal,
Interests.TractId,
Leases.NetAcres,
UnitTracts.AcInUnit
FROM (UnitTracts INNER JOIN (((WorkingInterestGroups INNER JOIN Interests ON WorkingInterestGroups.Id = Interests.WorkingInterestGroupId)
INNER JOIN Tracts ON Interests.TractId = Tracts.Id)
INNER JOIN Leases ON WorkingInterestGroups.LeaseId = Leases.Id)
ON UnitTracts.TractId = Tracts.Id)
LEFT JOIN AdditionalLeaseInfo ON Leases.Id = AdditionalLeaseInfo.LeaseId
where unitId = 21
GROUP BY UnitTracts.Id,
UnitTracts.UnitId,
Leases.Id,
Leases.Lessor,
Leases.Lessee,
Leases.Alias,
Leases.LeaseDate,
Leases.GrossAcres,
IIf([Page] Is Null,[VolumeDocumentNumber],[VolumeDocumentNumber] + '/' + [Page]),
Leases.Legal,
Interests.TractId,
Leases.NetAcres,
UnitTracts.AcInUnit
This the query I got but it returns less records. I tried to convert from SQL to LINQ but it did not work. I really stuck now.
var leases = (from l in db.Leases
where l.Active
join ali in db.AdditionalLeaseInfoes on l.Id equals ali.LeaseId
where ali.Active
join wig in db.WorkingInterestGroups on l.Id equals wig.LeaseId
where wig.Active
join interest in db.Interests on wig.Id equals interest.WorkingInterestGroupId
where interest.Active
join tr in db.Tracts on interest.TractId equals tr.Id
where tr.Active
join ut in db.UnitTracts on tr.Id equals ut.TractId
where ut.Active
group new { l, wig, interest, tr, ali, ut } by
new
{
Id = ut.Id,
UnitId = ut.UnitId,
LeaseId = l.Id,
Lessor = l.Lessor,
Lessee = l.Lessee,
Alias = l.Alias,
LeaseDate = l.LeaseDate,
GrossAcres = l.GrossAcres,
VolPg = l.Page == null ? l.VolumeDocumentNumber : l.VolumeDocumentNumber + "/" + l.Page,
Legal = l.Legal,
TractId = interest.TractId,
NetAcres = l.NetAcres,
AcInUnit = ut.AcInUnit
} into lease
select new LeasesViewModel
{
UnitId = lease.Key.UnitId,
TractId = lease.Key.TractId,
LeaseId = lease.Key.LeaseId,
LeaseAlias = lease.Key.Alias,
Pooling = lease.Where(x => x.l.Id == lease.Key.LeaseId).Select(x => x.l.NoPooling).FirstOrDefault() ? "No" :
lease.Where(x => x.l.Id == lease.Key.LeaseId).Select(x => x.l.Pooling).FirstOrDefault() ? "Yes" : "No Review",
Lessor = lease.Key.Lessor,
GrossAc = lease.Key.GrossAcres
}).Where(x => x.UnitId == unitId).OrderBy(x => x.TractId).ToList();
Thanks for help!!
Thanks for help!!
Thanks for help!!
Thanks for help!!
I modeled you query with classes to get syntax correct :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<WorkingInterestGroups> workingInterestGroups = new List<WorkingInterestGroups>();
List<UnitTracts> unitTracts = new List<UnitTracts>();
List<Tracts> tracts = new List<Tracts>();
List<Leases> leases = new List<Leases>();
List<AdditionalLeaseInfo> additionalLeaseInfos = new List<AdditionalLeaseInfo>();
List<Interests> interests = new List<Interests>();
var results = (from unitTract in unitTracts
join tract in tracts on unitTract.TractId equals tract.Id
join interest in interests on tract.Id equals interest.TractId
join workingInterestGroup in workingInterestGroups on interest.WorkingInterestGroupId equals workingInterestGroup.Id
join lease in leases on workingInterestGroup.LeaseId equals lease.Id
join additionalLeaseInfo in additionalLeaseInfos on lease.Id equals additionalLeaseInfo.LeaseId
where unitTract.UnitId == "21"
select new { unitTract = unitTract, tract = tract, interest = interest, workingInterestGroup = workingInterestGroup,
lease = lease, additionalLeaseInfo = additionalLeaseInfo}).ToList();
var groups = results.GroupBy(x => new
{
x.unitTract.Id,
x.unitTract.UnitId,
x.lease.Lessor,
x.lease.Lessee,
x.lease.Alias,
x.lease.LeaseDate,
x.lease.GrossAcres,
x.lease.Legal,
x.interest.TractId,
x.lease.NetAcres,
x.unitTract.AcInUnit
})
.ToList();
}
}
public class WorkingInterestGroups
{
public string Id { get; set; }
public string LeaseId { get; set; }
}
public class UnitTracts
{
public string TractId { get; set; }
public string Id { get; set; }
public string UnitId { get; set; }
public string AcInUnit { get;set;}
}
public class Tracts
{
public string Id { get; set; }
}
public class Leases
{
public string Id { get; set; }
public string Lessor { get; set; }
public string Lessee { get; set; }
public string Alias { get; set; }
public string LeaseDate { get; set; }
public string GrossAcres { get; set; }
public string Legal { get; set; }
public string NetAcres { get; set; }
}
public class AdditionalLeaseInfo
{
public string LeaseId { get; set;}
}
public class Interests
{
public string TractId { get; set; }
public string WorkingInterestGroupId { get; set; }
}
}
I have the following query in linq, which takes 2 lists as a data source. The first contains a list of ProductID and its description
public class Venta
{
public string ProductoId { get; set; }
public string clienteRut { get; set; }
}
public class Ventas
{
public List<Venta> lstVentas { get; set; }
}
and the other list has the products sold
public class Productos
{
public List<Producto> lstProductos { get; set; }
}
public class Producto
{
public string id { get; set; }
public string name { get; set; }
}
I need to consult the 5 most sold products, ordered by quantity from the most sold, to the least sold.
So far I have the following linq query, but I do not know how to do it so that I am given the list of the first 5, ordered from highest to lowest based on the quantity (cont)
Venta vta1 = new Venta();
vta1.ProductoId = "1";
vta1.clienteRut = "121370654";
Venta vta2 = new Venta();
vta2.ProductoId = "2";
vta2.clienteRut = "121370654";
Venta vta3 = new Venta();
vta3.ProductoId = "3";
vta3.clienteRut = "121370654";
List<Venta> lstVentasDia = new List<Venta>();
lstVentasDia.Add(vta1);
lstVentasDia.Add(vta2);
lstVentasDia.Add(vta3);
VentasDia vtas = new VentasDia();
vtas.date = "2018-05-01";
vtas.lstVentas = lstVentasDia;
var Lista5Top = from vendidos in vtas.lstVentas
orderby vendidos.ProductoId
group vendidos by vendidos.ProductoId into Grupo
select new { key = Grupo.Key, cont = Grupo.Count() };
I need in addition to that group of result, add the name of the product that is in the list Products, and order it by quantity sold of greater to less only the first 5
Thankful in advance
Gloria
Try following :
Productos productos = new Productos();
var Lista5Top = (from vendidos in vtas.lstVentas
join prod in productos.lstProductos on vendidos.ProductoId equals prod.id
select new { id = vendidos.ProductoId, rut = vendidos.clienteRut, name = prod.name })
.OrderBy(x => x.id)
.GroupBy(x => x.id)
.Select(x => new { id = x.Key, cont = x.Count(), name = x.FirstOrDefault().name })
.OrderByDescending(x => x.cont)
.Take(5).ToList();
Is is possible to have a linq query that populates a class with List for any outer join subqueries?
I've tried various variations of this, but can't get it to work.
Another option would be to populate the class by having more queries, but that would be bad performance wise.
Here's an example, where I try to populate MyClass, using a single query
var result = from p in PersonTable
join cars in CarTable on p.id equals cars.id_person into carsGroup.DefaultIfEmpty()
select new MyClass
{
Person = new Person
{
Id = p.id,
Name = p.name
},
Cars = new List<Car>()
{
Id = carsGroup....??
}
}
public class MyClass
{
public Person Person { get; set; }
public List<PersonCar> Cars { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class PersonCar
{
public int Id { get; set; }
pubint int IdPerson {get; set;}
public string Description { get; set; }
}
The LINQ query you have provide is incorrect. The following is a Test that will demonstrate functionality that you're probably looking for:
[TestMethod]
public void TestMethod1()
{
var PersonTable = new List<Person>
{
new Person
{
Id = 1,
Name = "Test1"
},
new Person
{
Id = 2,
Name = "Test2"
},
};
var CarTable = new List<PersonCar>
{
new PersonCar
{
Id = 1,
IdPerson = 2
},
new PersonCar
{
Id = 2,
IdPerson = 3
}
};
var result = (from person in PersonTable
join cars in CarTable on person.Id equals cars.IdPerson into carsGroup
from args in carsGroup.DefaultIfEmpty()
select new MyClass
{
Person = person,
Cars = carsGroup.ToList()
}).ToList();
Assert.AreEqual(2, result.Count);
Assert.AreEqual(1, result.Count(res => res.Cars.Count == 0));
Assert.AreEqual(1, result.Count(res => res.Cars.Count == 1));
}