LINQ: Using INNER JOIN, Group and SUM and HAVING - c#

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; }
}
}

Related

SQL to Linq then to Lambda using navigation properties

I'm trying to build a lambda expression to get the grand total but I'm still struggling to achieve the desired result. I've managed to achieve the same using SQL and LINQ using joints but it would be great if someone could give me a hand to re-write the query using lambda and navigation properties (without joints).
SQL Query:
SELECT SUM(a.[Quantity] * (a.[Price] + b.[ExtraValue])) + SUM(d.SubMealTotal * a.[Quantity]) AS [Total]
FROM [dbo].[OrderedMeals] a
INNER JOIN [dbo].[OrderedMealPortions] b
ON a.Id = b.[OrderedMealId]
LEFT OUTER JOIN (SELECT OrderedMealId, Sum(Price) AS SubMealTotal FROM [dbo].[OrderedSubMeals]
GROUP BY OrderedMealId) AS d
ON a.Id = d.[OrderedMealId]
WHERE a.[Quantity] > 0
Then the LINQ - Please let me know if I'm missing something here or there is a better way:
(from orderedMeal in _context.OrderedMeals.Where(x => x.Quantity > 0)
join orderedMealPortion in _context.OrderedMealPortions
on orderedMeal.Id equals orderedMealPortion.OrderedMealId
join orderedSubMeal in _context.OrderedSubMeals
on orderedMeal.Id equals orderedSubMeal.OrderedMealId into gs
from subOrderedSubMeal in gs.DefaultIfEmpty()
group subOrderedSubMeal by new { subOrderedSubMeal.OrderedMealId, orderedMeal.Price, orderedMeal.Quantity, orderedMealPortion.ExtraValue } into g
select new
{
MealTotal = (g.Key.ExtraValue + g.Key.Price) * g.Key.Quantity + g.Sum(x => x.Price * g.Key.Quantity),
}).Sum(x => x.MealTotal); // Not sure how to get the sum using LINQ
Entities:
public class OrderedMeal
{
public int Id { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public int OrderedMealPortionId { get; set; }
public OrderedMealPortion? OrderedMealPortion { get; set; }
public ICollection<OrderedSubMeal>? OrderedSubMeals { get; set; }
}
public class OrderedMealPortion
{
public int Id { get; set; }
public int OrderedMealId { get; set; }
public OrderedMeal? OrderedMeal { get; set; }
public decimal? ExtraValue { get; set; }
}
public class OrderedSubMeal
{
public int Id { get; set; }
public int OrderedMealId { get; set; }
public OrderedMeal? OrderedMeal { get; set; }
public decimal Price { get; set; }
}
I can't test with a database, but I think this implements the query logic and will produce the same result:
var ans = OrderedMeals
.Where(om => om.Quantity > 0 && om.OrderedMealPortion != null)
.Sum(om => om.Quantity * (om.Price +
om.OrderedMealPortion!.ExtraValue +
(om.OrderedSubMeals != null ? om.OrderedSubMeals.Sum(osm => osm.Price) : 0)) );
This is direct translation from the SQL:
var groupingQuery =
from sm in _context.OrderedSubMeals
group sm by new { sm.OrderedMealId } into g
select new
{
g.Key.OrderedMealId,
SubMealTotal = g.Sum(x => x.Price)
};
var query =
from om in _context.OrderedMeals
join g in groupingQuery on om.Id equals g.OrderedMealId into gj
from g in gj.DefaultIfEmpty()
where om.Quantity > 0
select new { om, om.OrderedMealPortion, g };
var result = query.Sum(x => x.om.Quantity * (x.om.Price + x.OrderedMealPortion.ExtraValue + x.g.SubMealTotal));
But I have feeling that query can be simplified without grouping.

How to Get Last Record Using LINQ - Entity Framework in SQLite

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; }
}

Order by (orderby) the sum of two columns in LINQ [duplicate]

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; }
}
}

SQL to LINQ with multiple joins and group by

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; }
}
}

LINQ query expressions and extension methods

How to make this expression using the methods of exptension, but (!) not using anonymous types?
from p in posts
join u in context.oxite_Users on p.CreatorUserID equals u.UserID
join pa in context.oxite_PostAreaRelationships on p.PostID equals pa.PostID
join a in context.oxite_Areas on pa.AreaID equals a.AreaID
let c = getCommentsQuery(p.PostID)
let t = getTagsQuery(p.PostID)
let tb = getTrackbacksQuery(p.PostID)
let f = getFilesQuery(p.PostID)
where p.State != (byte)EntityState.Removed
orderby p.PublishedDate descending
select new Post
{ area = a, comments = c } e.t.c.
The key here is to introduce a tuple that encapsulates the combined state of the join operations and other lets. I can't repro your environment just from that, but here's a limited example that should make it clear(ish);
using System.Linq;
static class Program
{
static void Main()
{
var users = new User[0]; // intentionally 0; only exists to prove compiles
var orders = new Order[0];
var query = users.Join(orders, user => user.UserId, order => order.OrderId, (user,order) => new UserOrderTuple(user,order))
.Where(tuple => tuple.State != 42).OrderByDescending(tuple => tuple.Order.OrderId)
.Select(tuple => new ResultTuple { Comment = tuple.Comment });
}
}
class ResultTuple
{
public string Comment { get; set; }
}
class UserOrderTuple
{
public UserOrderTuple(User user, Order order)
{
User = user;
Order = order;
Comment = "some magic that gets your comment and other let";
State = 124;
}
public string Comment { get; private set; }
public int State { get; private set; }
public User User { get; private set; }
public Order Order { get; private set; }
}
class User
{
public int UserId { get; set; }
}
class Order
{
public int UserId { get; set; }
public int OrderId { get; set; }
}

Categories

Resources