Linq Group By & Sum Query On Multiple Columns - c#

var fpslist = db.FPSinformations.Where(x => x.Godown_Code != null && x.Godown_Code == godownid).ToList();
var data1 = fpslist.GroupBy(x => x.Ration_Card_Type1)
.Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count1)
}).ToList();
var data2 = fpslist.GroupBy(x => x.Ration_Card_Type2)
.Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count2)
}).ToList();
var data3 = fpslist.GroupBy(x => x.Ration_Card_Type3)
.Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count3)
}).ToList();
var data4 = fpslist.GroupBy(x => x.Ration_Card_Type4)
.Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count4)
}).ToList();
var data5 = fpslist.GroupBy(x => x.Ration_Card_Type5)
.Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count5)
}).ToList();
var GodownRCCount = data1.Where(x => x.CardType_Name != null).ToList();
var GodownRCCounts = GodownRCCount;
GodownRCCount = data2.Where(x => x.CardType_Name != null).ToList();
GodownRCCounts.AddRange(GodownRCCount);
GodownRCCount = data3.Where(x => x.CardType_Name != null).ToList();
GodownRCCounts.AddRange(GodownRCCount);
GodownRCCount = data4.Where(x => x.CardType_Name != null).ToList();
GodownRCCounts.AddRange(GodownRCCount);
GodownRCCount = data5.Where(x => x.CardType_Name != null).ToList();
GodownRCCounts.AddRange(GodownRCCount);
I have 10 Columns in My Database Like
Ration_Card_Type1
Ration_card_count1
Ration_Card_Type2
Ration_card_count2
Ration_Card_Type3
Ration_card_count3
Ration_Card_Type4
Ration_card_count4
Ration_Card_Type5
Ration_card_count5
Now What I want is to get the sum of Ration_Card_Counts and Its Type from its Type
Expected Output :
CardType_Name
CardType_Count
Well the above code works fine but I want to optimize it in max possible way as this will be inside a Loop and there are about 1.5 million records.
Thanks

Union should operate faster than AddRange!
you can try the following:
var data = (from g in fpslist.GroupBy(x => x.Ration_Card_Type1).Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count1)
}).Union(
fpslist.GroupBy(x => x.Ration_Card_Type2).Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count2)
})).Union(
fpslist.GroupBy(x => x.Ration_Card_Type3).Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count3)
})).Union(
fpslist.GroupBy(x => x.Ration_Card_Type4).Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count4)
})).Union(
fpslist.GroupBy(x => x.Ration_Card_Type5).Select(x => new
{
CardType_Name = x.Key,
CardType_Count = x.Sum(y => y.Ration_Card_Count5)
}))
select g).ToList();
In general from grouping I would go with Thomas!
Database grouping is far better for me, since you are fetching the data required aggregated and therefore the data transferred over the network if much less!

You can rewrite the same query using SQL and put some indexes(performance) :
SELECT Ration_Card_Type = Ration_Card_Type1, Ration_Card_Count = sum(Ration_card_count1)
FROM
FPSinformations
GROUP BY
Ration_Card_Type1
UNION
SELECT Ration_Card_Type = Ration_Card_Type2, Ration_Card_Count = sum(Ration_card_count2)
FROM
FPSinformations
GROUP BY
Ration_Card_Type2
UNION
SELECT Ration_Card_Type = Ration_Card_Type3, Ration_Card_Count = sum(Ration_card_count3)
FROM
FPSinformations
GROUP BY
Ration_Card_Type3
UNION
SELECT Ration_Card_Type = Ration_Card_Type4, Ration_Card_Count = sum(Ration_card_count4)
FROM
FPSinformations
GROUP BY
Ration_Card_Type4
UNION
SELECT Ration_Card_Type = Ration_Card_Type5, Ration_Card_Count = sum(Ration_card_count5)
FROM
FPSinformations
GROUP BY
Ration_Card_Type5
I am not sure but this query make me think about UNPIVOT maybe you can investigate in this direction too.

Related

Evaluate locally ToDictionary after GroupBy

I have the following Entity Framework Core query:
var result = await products
.Select(x => new {
PackageId = x.PackageId,
Price = x.Price
})
.GroupBy(x => x.PackageId)
.Select(x => new {
PackageId = x.Key,
TotalPrice = x.Sum(y => y.Price)
})
.ToDictionaryAsync(x => x.PackageId, x => new Model {
TotalPrice = x.TotalPrice
});
I was able to make this query evaluate on the server.
Is there a way to simplify it and still make sure it evaluates on the server?
Try this.
var result = await products
.GroupBy(x => x.PackageId)
.Select(x => new {
PackageId = x.Key,
TotalPrice = x.Sum(y => y.Price)
})
.ToDictionaryAsync(x => x.PackageId, x => new Model {
TotalPrice = x.TotalPrice
});
EF will take care about not to load unnecessary data.

Simplifying a Linq query by using Include instead of Join

I've been asked to simplify the following Linq query:
var orders = db.Orders
.Join(db.Shipments,
o => o.OrderID,
s => s.OrderID,
(o, s) => new { Order = o, Shipment = s })
.Join(db.LineItems,
s => s.Shipment.ShipmentID,
l => l.ShipmentID,
(s, l) => new { Order = s.Order, Shipment = s.Shipment, LineItem = l })
.Join(db.StatusTypes,
s => s.Shipment.StatusTypeID,
st => st.StatusTypeID,
(s, st) => new { Order = s.Order, Shipment = s.Shipment, LineItem = s.LineItem, Description = st.ExternalDescription })
.Where(x => x.Order.AccountID == accountId)
.GroupBy(x => x.Order.OrderNumber)
.ToList()
.Select(
x => new OrderStatusViewModel
{
Date = x.Max(y => y.Order.Created),
OrderNumber = x.Key,
Cost = x.Sum(y => y.LineItem.UnitPrice).ToString(),
Status = x.Max(y => y.Description)
}
);
By replacing the Joins with Includes. I've searched around, and I've discovered that Joins and Includes are somewhat equivalent. But I can't figure out how to convert this query to one that uses includes instead of joins. Is it actually less code and simpler to use includes instead of joins here?
I strongly suggest you to use navigation properties instead of manual builded joins. It will be more efficent and controlable. Read this article.
If you would convert your query to navigation property form by using Include, it would seem like that;
var orders = db.Orders
.Include(x => x.Shipments)
.Include(x => x.Shipments.Select(y => y.LineItems))
.Include(x => x.Shipments.Select(y => y.StatusType))
.Where(x => x.Order.AccountID == accountId)
.GroupBy(x => x.Order.OrderNumber)
.ToList()
.Select(
x => new OrderStatusViewModel
{
Date = x.Max(y => y.Created),
OrderNumber = x.Key,
Cost = x.LineItems.Sum(k => k.UnitPrice),
Status = x.Max(y => y.Description)
}
);
But, as I said, you should define the navigation properties for entities first.
var orders = db.Orders
.Include("Shipments")
.Include("Shipments.LineItems")
.Include("Shipments.StatusTypes")
.Where(x => x.Order.AccountID == accountId)
.GroupBy(x => x.Order.OrderNumber)
.ToList()
.Select(
x => new OrderStatusViewModel
{
Date = x.Max(y => y.Order.Created),
OrderNumber = x.Key,
Cost = x.Sum(y => y.LineItem.UnitPrice).ToString(),
Status = x.Max(y => y.Description)
}
);
i not tested above code ,just try
ObjectQuery.Include Method (String)

How do i do the "IN" and "DISTINCT of SQL to LINQ

SELECT DISTINCT MarketTemplateId AS MarketTemplateID
FROM Market
WHERE Market.FixtureId = ? And
Market.MarketTemplateId In
('MW3W', '1HTG', 'FTCS', 'HTFT', 'MTG2W', 'MW3W1H','FTCSALT')
how would i produce this in LINQ because i tried the below code and it doesn't work
var result6 = entityTrading.Markets
.Where(p => p.FixtureId == InternalFixtureID_F.ToString())
.FirstOrDefault(p => MarketTemplateIds.Contains(p.MarketTemplateId));
List<string> MarketTemplateIds = new List<string>{ "MW3W", "1HTG", "FTCS", "HTFT", "MTG2W", "MW3W1H","FTCSALT" };
var result6 = entityTrading.Markets
.Where(p => p.FixtureId == InternalFixtureID_F.ToString()
and MarketTemplateIds.Contains(p.MarketTemplateId ))
.Select( u => u.MaketTemplateId).Distinct();
How about
var id = InternalFixtureID_F.ToString();
var result6 = entityTrading.Markets
.Where(p => p.FixtureId == id && MarketTemplateIds.Contains(p.MarketTemplateId))
.Select(m => m.MarketTemplateId)
.Distinct();

Linq to find lasted record in group

I want add a new column to find which is lasted record in group.
Can I write subquery in Select() method?
I have try this
var test = DailyPeriods.Where(x => x.BookingDate == "2016/12/30")
.Select(x =>
new
{
PERIOD_GROUP_ID = x.PeriodGroupID,
PERIOD_NAME = x.PeriodName,
New_Column = DailyPeriods
.Where(z => z.BookingDate == "2016/12/30")
.Select(a =>
new
{
PeriodGroupID = a.PeriodGroupID,
period_name = a.PeriodName
}
)
.GroupBy(b => b.period_name)
.Select(g => g.Last().PeriodGroupID)
.Contains(x.PeriodName)
})
But will occur this error
"column not in scope: A:2211708.C(BOOKING_DATE)"
Try this..
var lastRecords = periodList.GroupBy(l => l.PeriodName)
.Select(x => new { PeriodName = x.Key,
PeriodGroupId = x.OrderBy(l => l.PeriodGroupId).Last().PeriodGroupId});
var result = from period in periodList
from lastRec in lastRecords.Where(r => r.PeriodGroupId == period.PeriodGroupId
&& r.PeriodName == period.PeriodName)
.DefaultIfEmpty()
select new { period.PeriodGroupId,period.PeriodName, New_Column=lastRec==null?false:true };

LINQ query to dictionary

I'm trying to convert below LINQ query result into dictionary
var browser = (from tbf in context.tblFeedBacks
where tbf.email == dboard.userEmail
select tbf).GroupBy(l => l.browser)
.Select(g => new
{
browser = g.Key,
count = g.Select(l => l.browser).Distinct().Count()
});
It gives me a compilation error.
var browser = (from tbf in context.tblFeedBacks
where tbf.email == dboard.userEmail
select tbf).GroupBy(l => l.browser)
.Select(g => new
{
browser = g.Key,
count = g.Select(l => l.browser).Distinct().Count()
}).ToDictionary<string, double>(x => x.browser,y=>y.count);
Instance argument: cannot convert from
'System.Linq.IQueryable' to
'System.Linq.ParallelQuery'
got it working.
var browser = (from tbf in context.tblFeedBacks
where tbf.email == dboard.userEmail
select tbf).GroupBy(l => l.browser)
.Select(g => new
{
browser = g.Key,
count = g.Select(l => l.browser).Count()
}).ToDictionary(x => x.browser, x => x.count);

Categories

Resources