max and group by question with LINQ - c#

I want to group the below query by GetSetDomainName and select the row which has the maximum GetSetKalanGun.In other words, I am trying to get the row with the maximum KALANGUN among those which have the same DOMAINNAME.
var kayitlar3 = (
from rows in islemDetayKayitListesi
select new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
}).AsQueryable();
This is what I get
KAYITNO DOMAINNAME KALANGUN
1 asdf.com 30
2 domnam.com 172
3 asdf.com 40
4 xyz.com 350
This is what I want
KAYITNO DOMAINNAME KALANGUN
2 domnam.com 172
3 asdf.com 40
4 xyz.com 350
var islemDetayKayitListesi = new List<IslemDetayKayit>();
islemDetayKayitListesi get filled with a foreach loop, with no problem
And that is what IslemDetayKayit looks like
public class IslemDetayKayit
{
public int GetSetKayitNo { get; set; }
public string GetSetHesapAdi { get; set; }
public string GetSetUrunNo { get; set; }
public string GetSetUrunAdi { get; set; }
public double GetSetUrunMiktar { get; set; }
public string GetSetIslemTarihi { get; set; }
public string GetSetHizmetDurumu { get; set; }
public string GetSetToplamTutar { get; set; }
public string GetSetHizmetBaslangicTarihi { get; set; }
public string GetSetHizmetBitisTarihi { get; set; }
public int GetSetKalanGun { get; set; }
public string GetSetSiparisDurumu { get; set; }
public string GetSetDomainName { get; set; }
}
EDIT : I figured out that there was some other problem in my code, and corrected it.After that all the answer I had to this question works.Thank you for helping and teaching me new things.

This will do the trick:
var q =
from item in kayitlar3
group item by item.DOMAINNAME into g
select g.OrderByDescending(i => i.KALANGUN).First();
You can also try this:
var q =
from row in islemDetayKayitListesi
group row by row.GetSetDomainName into g
let highest = g.OrderByDescending(r => r.GetSetKalanGun).First()
select new
{
KAYITNO = highest.GetSetKayitNo,
DOMAINNAME = g.Key,
KALANGUN = highest.GetSetKalanGun
};
Note that this would yield the same results. If it doesn't, there is a problem with your code that we can't see by looking at the information that you posted.

You could use:
var kayitlar3 =
islemDetayKayitListesi.
Select(rows =>
new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun,
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
}).
GroupBy(a =>
//To ignore case and trailing/leading whitespace
a.DOMAINNAME.ToUpper().Trim()).
Select(g =>
g.OrderByDescending(a => a.KALANGUN).FirstOrDefault()).
AsQueryable();
EDIT:
So using this code:
List<Thing> islemDetayKayitListesi = new List<Thing>();
Thing a = new Thing() { GetSetDomainName = "abc.com", GetSetKayitNo = 1,
GetSetKalanGun = 40 };
Thing b = new Thing() { GetSetDomainName = "abc.com", GetSetKayitNo = 2,
GetSetKalanGun = 300 };
Thing c = new Thing() { GetSetDomainName = "xyz.com", GetSetKayitNo = 3,
GetSetKalanGun = 400 };
Thing d = new Thing() { GetSetDomainName = "123.com", GetSetKayitNo = 4,
GetSetKalanGun = 124 };
islemDetayKayitListesi.Add(a);
islemDetayKayitListesi.Add(b);
islemDetayKayitListesi.Add(c);
islemDetayKayitListesi.Add(d);
var kayitlar3 =
islemDetayKayitListesi.
Select(rows =>
new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun,
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
}).
GroupBy(anon =>
anon.DOMAINNAME).
Select(g =>
g.OrderByDescending(anon => anon.KALANGUN).First()).
AsQueryable();
kayitlar3.ToList().
ForEach(anon => Console.WriteLine("{0}, {1}, {2}",
anon.KAYITNO, anon.DOMAINNAME, anon.KALANGUN));
struct Thing
{
public int GetSetKayitNo { get; set; }
public int GetSetHesapAdi { get; set; }
public int GetSetUrunNo { get; set; }
public int GetSetUrunAdi { get; set; }
public int GetSetUrunMiktar { get; set; }
public int GetSetIslemTarihi { get; set; }
public int GetSetHizmetDurumu { get; set; }
public int GetSetToplamTutar { get; set; }
public int GetSetHizmetBaslangicTarihi { get; set; }
public int GetSetHizmetBitisTarihi { get; set; }
public int GetSetKalanGun { get; set; }
public string GetSetDomainName { get; set; }
public int GetSetSiparisDurumu { get; set; }
}
I get the expected output:
2, abc.com, 300
3, xyz.com, 400
4, 123.com, 124

After clarification about your desired output, this will return the row with the top KALANGUN per DOMAINNAME:
var kayitlar3 = (
from rows in islemDetayKayitListesi
select new
{
KAYITNO = rows.GetSetKayitNo,
HESAPADI = rows.GetSetHesapAdi,
URUNNO = rows.GetSetUrunNo,
URUNADI = rows.GetSetUrunAdi,
URUNMIKTAR = rows.GetSetUrunMiktar,
ISLEMTARIHI = rows.GetSetIslemTarihi,
HIZMETDURUMU = rows.GetSetHizmetDurumu,
TOPLAMTUTAR = rows.GetSetToplamTutar,
HIZMETBASLANGICTARIHI = rows.GetSetHizmetBaslangicTarihi,
HIZMETBITISTARIHI = rows.GetSetHizmetBitisTarihi,
KALANGUN = rows.GetSetKalanGun
DOMAINNAME = rows.GetSetDomainName,
SIPARISDURUMU = rows.GetSetSiparisDurumu
})
.GroupBy(rr => rr.DOMAINNAME)
.SelectMany(gg => gg.OrderByDescending(rr => rr.KALANGUN).First());

Try
from rows in islemDetayKayitListesi
group rows by new { rows.GetSetDomainName} into results
let MaxKALANGUN = results.Max(i=>i.KALANGUN)
select new
{
KAYITNO = results.First(i=>i.KALANGUN== MaxKALANGUN).GetSetKayitNo
DOMAINNAME = results.Key.GetSetDomainName ,
KALANGUN = MaxKALANGUN
}
If you want the complete class, try
from rows in islemDetayKayitListesi
group rows by new { rows.GetSetDomainName} into results
let MaxKALANGUN = results.Max(i=>i.KALANGUN)
select results.First(i=>i.KALANGUN== MaxKALANGUN)

Related

Filter data from 2 lists with diferent models C#

I have this models
public class RoutingAttributeModel
{
public int Bus_No { get; set; }
public int Attribute_No { get; set; }
public string Attribute_Name { get; set; }
public string Status { get; set; }
public string Notes { get; set; }
}
public class AgentRoutingAttributeModel
{
public int Agent_No { get; set; }
public int Bus_No { get; set; }
public int Attribute_No { get; set; }
public string Attribute_Name { get; set; }
public string Status { get; set; }
}
List<RoutingAttributeModel> lstComplete = new List<RoutingAttributeModel>();
List<AgentRoutingAttributeModel> lstAssigned = new List<AgentRoutingAttributeModel>();
Filled this with some data
Is it possible to filter with Linq? I want to save in a new list the diferent content between lstComplete and lstAssigned
I was trying to join both lists but got stuck there
var results1 = from cl in lstComplete
join al in lstAssigned
on cl.Attribute_No equals al.Attribute_No
select cl;
you can use linq
as my understanding, you try to find linked by attribute_No records and have a list of not matching properties?
lstComplete.Add(new RoutingAttributeModel(){
Attribute_Name = "aaa",
Attribute_No = 1,
Bus_No = 1,
Notes = "",
Status = "status"
});
lstAssigned.Add(new AgentRoutingAttributeModel()
{
Attribute_No = 1,
Agent_No = 10,
Bus_No = 1,
Attribute_Name = "bbb",
Status = "status2"
});
var lst = lstComplete
.Join(lstAssigned,
complete => complete.Attribute_No,
assigned => assigned.Attribute_No,
(complete, assigned) => new { lstComplete = complete, lstAssigned = assigned })
.Select(s => new { s.lstComplete, s.lstAssigned})
.Where(w=>
w.lstAssigned.Attribute_Name != w.lstComplete.Attribute_Name
|| w.lstAssigned.Bus_No != w.lstComplete.Bus_No
)
.ToList()
.Dump();
so result would be
You could try the following query
var filteredList = lstComplete
.Where(x => !lstAssigned.Any(y => y.Attribute_No == x.Attribute_No));

Extracting Items over an List<T> of List<T>

I am trying to retrieve records from a List<T> of List<T> and seek your help in getting it.
I am trying to fetch items where overdues.Accounts.AccountId = 'JKB1' and how can i do it over the below List Items.
public class OverdueModel
{
public string Slab { get; set; }
public double Value { get; set; }
public double Percentage { get; set; }
public List<OverdueSlabAccounts> Accounts { get; set; }
}
public class OverdueSlabAccounts
{
public string AccountId { get; set; }
public string AccountName { get; set; }
public string SalesCode { get; set; }
public string Value { get; set; }
}
void Main(){
List<OverdueModel> overdues = new List<OverdueModel>();
List<OverdueSlabAccounts> accounts = new List<OverdueSlabAccounts>();
//For T3
accounts.Clear();
accounts.Add(new OverdueSlabAccounts()
{
AccountId = "JKB1",
AccountName = "JKB1",
SalesCode = "JKB",
Value = "500"
});
accounts.Add(new OverdueSlabAccounts()
{
AccountId = "JKB2",
AccountName = "JKB2",
SalesCode = "JKB",
Value = "500"
});
overdues.Add(new OverdueModel()
{
Slab = "T3",
Value = 1000,
Percentage = 0,
Accounts = accounts
});
//For T4
accounts.Clear();
accounts.Add(new OverdueSlabAccounts()
{
AccountId = "JKB1",
AccountName = "JKB1",
SalesCode = "JKB",
Value = "1000"
});
overdues.Add(new OverdueModel()
{
Slab = "T4",
Value = 1000,
Percentage = 0,
Accounts = accounts
});
}
You can use Where and Any in combination for this :
var result = overdues
.Where(overdue => overdue.Accounts
.Any(account => account.AccountId == "JKB1"));
This will filter those overdues for which associated any Account has AccountId JKB1
You could use Linq for the purpose
var filteredList = overdues.Where(x=>x.Accounts.Any(c=>c.AccountId=="JKB1"));
For more information on Where and Any
Enumerable.Where : Refer
Enumerable.Any : Refer
Output
You can try this:
var account = accounts.Find(x => x.AccountId.Contains("JKB1")));
or
var account = accounts.Find(x => x.AccountId.Equals("JKB1")));
this will get you the specific account Id you are looking for.

Issue getting different types value of self join table

I have a self join table of population. Population is entered at village level and it should be automatically calculated on Union council(UC), Tehsil and District Level.
I am using .net MVC in this application. Following is my code
enum of population type
public enum UnitType
{
Village,
UC,
Tehsil,
Dist
}
population structure, here names of villages, UC, Tehsil and district are added
public class Village
{
public int Id { get; set; }
public string Name { get; set; }
public UnitType UnitType { get; set; }
public int? ParientId { get; set; }
public Village Parient { get; set; }
}
Enter population at village level
public class Population
{
public int Id { get; set; }
public int VillageId { get; set; }
public Village Village { get; set; }
public int NoOfPerson { get; set; }
}
I need the following output result. I can get the village level population but i am confused in getting related totals. Its looks very simple but i think i am not going in right direction.
POPULATION
Code Name Type Population
1 Chakwal Disttrict 20000 (total population of all tehsils)
2 Choa Tehsil 20000 (Tehsil total of two Union Councils)
3 Dalwal UC 14300 UC is total of village population
4 Waulah Village 9800
5 DalPur VIllage 4500
Dulmial UC 5700 UC is total of village population
Tatral Village 3400
Arar Village 2300
You need to join the two classes :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
List<Village> villages = new List<Village>() {
new Village() { Id = 1, Name = "Chakwal", UnitType = UnitType.Dist},
new Village() { Id = 2, Name = "Choa", UnitType = UnitType.Tehsil},
new Village() { Id = 3, Name = "Dalwal", UnitType = UnitType.UC},
new Village() { Id = 4, Name = "Waulah", UnitType = UnitType.Village},
new Village() { Id = 5, Name = "DalPur", UnitType = UnitType.Village},
new Village() { Id = 6, Name = "Dulmial", UnitType = UnitType.UC},
new Village() { Id = 7, Name = "Tatral", UnitType = UnitType.Village},
new Village() { Id = 8, Name = "Arar", UnitType = UnitType.Village}
};
List<Population> populations = new List<Population>() {
new Population() { Id = 1, NoOfPerson = 20000},
new Population() { Id = 2, NoOfPerson = 20000},
new Population() { Id = 3, NoOfPerson = 14300},
new Population() { Id = 4, NoOfPerson = 9800},
new Population() { Id = 5, NoOfPerson = 4500},
new Population() { Id = 6, NoOfPerson = 5700},
new Population() { Id = 7, NoOfPerson = 3400},
new Population() { Id = 8, NoOfPerson = 2300}
};
var results = (from v in villages
join p in populations on v.Id equals p.Id
select new { v = v, p = p }
).ToList();
StreamWriter writer = new StreamWriter(FILENAME);
writer.WriteLine("{0,25}","POPULATION");
writer.WriteLine("{0,-5}{1,-8}{2,-14}{3,-10}", "Code", "Name", "Type", "Population");
foreach (var result in results)
{
writer.WriteLine("{0,-5}{1,-8}{2,-14}{3,-10}", result.v.Id.ToString(), result.v.Name, result.v.UnitType.ToString(), result.p.NoOfPerson.ToString());
}
writer.Flush();
writer.Close();
}
}
public enum UnitType
{
Village,
UC,
Tehsil,
Dist
}
public class Village
{
public int Id { get; set; }
public string Name { get; set; }
public UnitType UnitType { get; set; }
public int? ParientId { get; set; }
public Village Parient { get; set; }
}
public class Population
{
public int Id { get; set; }
public int VillageId { get; set; }
public Village Village { get; set; }
public int NoOfPerson { get; set; }
}
}
Here is the answer for the question
var villages = db.Populations.Include(l => l.Village).ToList();
var ucpop = villages.GroupBy(l => l.UCId).Select(g=> new {
ucId = g.Key,
UcName = db.Villages.Find(g.Key),
VillageCount = g.Count(),
UCPop = g.Sum(l=>l.NoOfPerson),
villages = g.Where(l=>l.Village.UnitType == UnitType.Village).ToList()
}).ToList();
var tehpop = ucpop.GroupBy(l => l.UcName.ParientId).Select(g => new
{
tehId = g.Key,
tehName = db.Villages.Find(g.Key),
tehCount = g.Count(),
tehPop = g.Sum(l => l.UCPop),
uclist = g.Where(l=>l.UcName.UnitType == UnitType.UC).ToList()
}).ToList();
var distpop = tehpop.GroupBy(l => l.tehName.ParientId).Select(g => new
{
distId = g.Key,
distName = db.Villages.Find(g.Key),
distCount = g.Count(),
distPop = g.Sum(l => l.tehPop),
tehlist = g.Where(l => l.tehName.UnitType == UnitType.Tehsil).ToList()
}).ToList();

Merge sql into a stored procedure for better performace

I am still having real performance issue in a list there our 38 thousand entrys and I need to map them to another table for export I am thinking of moving it to stored proc but still worried what performance would be like there. The code works but takes a very long time to execute and wish to turn it into a stored proc.
private List<TradeItemsExport> MapTradeItems(List<TradeItems> tradeItem)
{
List<TradeItemsExport> retList = new List<TradeItemsExport>();
try
{
var StockImport = new StockItemExported();
List<StandardLookUpList> _AnalsisCodes = GetAnayalsisCodesForExportCode();
StandardLookUpList sport = new StandardLookUpList();
StandardLookUpList gender = new StandardLookUpList();
StandardLookUpList colour = new StandardLookUpList();
StandardLookUpList Size = new StandardLookUpList();
StandardLookUpList categorycode = new StandardLookUpList();
StandardLookUpList categorydesc = new StandardLookUpList();
StandardLookUpList subcategorycode = new StandardLookUpList();
StandardLookUpList subcategorydesc = new StandardLookUpList();
StandardLookUpList brandcode = new StandardLookUpList();
StandardLookUpList branddesc = new StandardLookUpList();
using (var db = new liveEntities1())
{
int count = 0;
foreach (var item in tradeItem)
{
count++;
bool hasprocessed = HasTransactionBeenProcessed(item.ItemCode);
if (hasprocessed == false)
{
var codesForThisItem = _AnalsisCodes.Where(w => w.ItemCode == item.ItemCode);
if (codesForThisItem.Any())
{
sport = codesForThisItem.FirstOrDefault(x => x.code == Constants.Sport);
gender = codesForThisItem.FirstOrDefault(x => x.code == Constants.Gender);
colour = codesForThisItem.FirstOrDefault(x => x.code == Constants.Colour);
Size = codesForThisItem.FirstOrDefault(x => x.code == Constants.Size);
categorycode = codesForThisItem.FirstOrDefault(x => x.code == Constants.Category);
categorydesc = codesForThisItem.FirstOrDefault(x => x.code == Constants.Category);
subcategorycode = codesForThisItem.FirstOrDefault(x => x.code == Constants.SubCategory);
subcategorydesc = codesForThisItem.FirstOrDefault(x => x.code == Constants.SubCategory);
brandcode = codesForThisItem.FirstOrDefault(x => x.code == Constants.Brand);
string SportCodeValue, SportDescValue;
if (sport == null)
{
SportCodeValue = "";
SportDescValue = "";
}
else
{
SportCodeValue = sport.LookupValue.ToString();
SportDescValue = sport.description;
}
string GenderCodeValue, GenderCodeDesc;
if (gender == null)
{
GenderCodeValue = "";
GenderCodeDesc = "";
}
else
{
GenderCodeValue = gender.LookupValue.ToString();
GenderCodeDesc = gender.description;
}
string ColourCodeValue, ColourCodeDesc;
if (colour == null)
{
ColourCodeValue = "";
ColourCodeDesc = "";
}
else
{
ColourCodeValue = colour.LookupValue.ToString();
ColourCodeDesc = colour.description;
}
string SizeCodeValue, SizeCodeDesc;
if (Size == null)
{
SizeCodeValue = "";
SizeCodeDesc = "";
}
else
{
SizeCodeValue = Size.LookupValue.ToString();
SizeCodeDesc = Size.description;
}
string CategoryCodeValue, CategoryCodeDesc;
if (categorycode == null)
{
CategoryCodeValue = "";
CategoryCodeDesc = "";
}
else
{
CategoryCodeValue = categorycode.LookupValue.ToString();
CategoryCodeDesc = categorydesc.description;
}
string subcategorycodevalue, subcategorycodedesc;
if (categorycode == null)
{
subcategorycodevalue = "";
subcategorycodedesc = "";
}
else
{
subcategorycodevalue = subcategorycode.LookupValue.ToString();
subcategorycodedesc = subcategorydesc.description;
}
string brandcodecodevalue, brandcodecodedesc;
if (brandcode == null)
{
brandcodecodevalue = "";
brandcodecodedesc = "";
}
else
{
brandcodecodevalue = brandcode.LookupValue.ToString();
brandcodecodedesc = brandcode.description;
}
retList.Add(new TradeItemsExport()
{
ItemCode = item.ItemCode,
BarCode = item.BarCode,
Description = item.Description,
SupplierCode = item.SupplierCode,
SupplierStockCode = item.SupplierStockCode,
Product_Group_Code = "",
Product_Group_Desc = "",
SportCode = SportCodeValue,
SportDesc = SportDescValue,
GenderCode = GenderCodeValue,
GenderDesc = GenderCodeDesc,
ColourCode = ColourCodeValue,
ColourDesc = ColourCodeDesc,
SizeCode = SizeCodeValue,
SizeDesc = SizeCodeDesc,
CategoryCode = CategoryCodeValue,
CategoryDesc = CategoryCodeDesc,
subcategorycode = subcategorycodevalue,
subcategorydesc = subcategorycodedesc,
BrandsCode = brandcodecodevalue,
BrandsDesc = brandcodecodedesc,
Vat = item.Vat,
GrossWeight = item.Weight,
CommodityCode = item.CommodityCode,
price_exVAT = item.price_exVAT,
price_incVAT = item.price_incVAT,
currentprice_exVAT = item.currentprice_exVAT,
currentprice_incVAT = item.currentprice_incVAT,
creation_date = item.creation_date,
Inactive_date = item.Inactive_date,
status = 1
});
Console.Write(String.Format("Exporting stock item {0} with a current record of {1} of {2} \n", item.ItemCode.ToString(), count.ToString(), tradeItem.Count.ToString()));
EFStockItemExported _newStockitemImported = new EFStockItemExported();
_newStockitemImported.StockItemID = item.ItemCode;
_newStockitemImported.IsProcessed = true;
_newStockitemImported.DateImported = DateTime.Now;
db.EFStockItemExporteds.Add(_newStockitemImported);
db.SaveChanges();
}
else
{
Console.Write(string.Format("Stock Items to Process [{0}] check the table and remove entry if wish to re process.", 0));
}
}
}
}
}
catch (Exception ex)
{
}
return retList;
}
My problem that this takes around 30 mins to compute the results which is very slow.
This is the sql that I am doing which is a view that is the tradeitem that I am passing.
SELECT
dbo.PLSupplierAccount.SupplierAccountNumber, dbo.PLSupplierAccount.PLSupplierAccountID, dbo.PLSupplierAccount.SupplierAccountName,
dbo.PLSupplierAccount.SYSCurrencyID, dbo.PLSupplierAccount.MainTelephoneAreaCode, dbo.PLSupplierAccount.MainTelephoneCountryCode,
dbo.PLSupplierAccount.MainTelephoneSubscriberNumber, dbo.PLSupplierAccount.MainFaxCountryCode, dbo.PLSupplierAccount.MainFaxSubscriberNumber,
dbo.PLSupplierAccount.MainFaxAreaCode, dbo.PLSupplierContact.ContactName, dbo.PLSupplierContact.Description, dbo.PLSupplierContact.FirstName,
dbo.PLSupplierContact.MiddleName, dbo.PLSupplierContact.LastName, loc.AddressLine1, loc.AddressLine2, loc.AddressLine3, loc.AddressLine4, loc.PostCode,
loc.City, loc.County,
CAST(CASE WHEN loc.Country = 'Ireland' THEN 'IRL'
WHEN loc.Country = 'Great Britain'
THEN 'GBR'
ELSE 'ERR'
END AS nvarchar(3)) AS Country,
dbo.SYSCurrency.SYSCurrencyISOCodeID, dbo.SYSCurrency.SYSExchangeRateTypeID, dbo.SYSCurrency.Name AS CurrencyDescription,
dbo.SYSCurrency.Symbol AS CurrencySymbol
FROM
dbo.PLSupplierAccount
INNER JOIN
dbo.PLSupplierContact ON dbo.PLSupplierAccount.PLSupplierAccountID = dbo.PLSupplierContact.PLSupplierAccountID
INNER JOIN
dbo.PLSupplierLocation AS loc ON dbo.PLSupplierAccount.PLSupplierAccountID = loc.PLSupplierAccountID
AND dbo.PLSupplierContact.PLSupplierLocationID = loc.PLSupplierLocationID
INNER JOIN
dbo.SYSCurrency ON dbo.PLSupplierAccount.SYSCurrencyID = dbo.SYSCurrency.SYSCurrencyID
My quesiton is how would I change the above to include a sub query that would do the same as this function is doing above.
The query for the codes look up which is again another view is below.
SELECT
dbo.StockItem.ItemID, dbo.StockItem.Code, dbo.StockItem.Name, dbo.StockItemSearchCatVal.SearchValueID, dbo.SearchValue.Name AS Expr1,
dbo.SearchCategory.Name AS Expr2
FROM
dbo.SearchCategory
INNER JOIN
dbo.SearchValue ON dbo.SearchCategory.SearchCategoryID = dbo.SearchValue.SearchCategoryID
INNER JOIN
dbo.StockItemSearchCatVal ON dbo.SearchCategory.SearchCategoryID = dbo.StockItemSearchCatVal.SearchCategoryID
AND dbo.SearchValue.SearchValueID = dbo.StockItemSearchCatVal.SearchValueID
INNER JOIN
dbo.StockItem ON dbo.StockItemSearchCatVal.ItemID = dbo.StockItem.ItemID
I just feel I would get more benefit changing this into a subquery so that I am just returning the results to .net I am using the filehelpers library to output the results set of MapTradeItems to csv so obv more things I can do the better on the server.
Obv I would need some kind of temporary table to loop through the results but how quick would that be in sql server compared to a .net for each loop.
This is the poco class which I have to reproduce to csv.
[DelimitedRecord(",")]
public class TradeItemsExport
{
[FieldOrder(1)]
public string ItemCode { get; set; }
[FieldOrder(2)]
public string BarCode { get; set; }
[FieldOrder(3)]
public string Description { get; set; }
[FieldOrder(4)]
public string SupplierCode { get; set; }
[FieldOrder(5)]
public string SupplierStockCode { get; set; }
[FieldOrder(6)]
public string Product_Group_Code { get; set; }
[FieldOrder(7)]
public string Product_Group_Desc { get; set; }
[FieldOrder(8)]
public string SportCode { get; set; }
[FieldOrder(9)]
public string SportDesc { get; set; }
[FieldOrder(10)]
public string GenderCode { get; set; }
[FieldOrder(11)]
public string GenderDesc { get; set; }
[FieldOrder(12)]
public string ColourCode { get; set; }
[FieldOrder(13)]
public string ColourDesc { get; set; }
[FieldOrder(14)]
public string SizeCode { get; set; }
[FieldOrder(15)]
public string SizeDesc { get; set; }
[FieldOrder(16)]
public string CategoryCode { get; set; }
[FieldOrder(17)]
public string CategoryDesc { get; set; }
[FieldOrder(18)]
public string subcategorycode { get; set; }
[FieldOrder(19)]
public string subcategorydesc { get; set; }
[FieldOrder(20)]
public string BrandsCode { get; set; }
[FieldOrder(21)]
public string BrandsDesc { get; set; }
[FieldOrder(22)]
public Nullable<short> Vat { get; set; }
[FieldOrder(23)]
public decimal GrossWeight { get; set; }
[FieldOrder(24)]
public string CommodityCode { get; set; }
[FieldOrder(25)]
public decimal price_exVAT { get; set; }
[FieldOrder(26)]
public Nullable<decimal> price_incVAT { get; set; }
[FieldOrder(27)]
public Nullable<decimal> currentprice_exVAT { get; set; }
[FieldOrder(28)]
public Nullable<decimal> currentprice_incVAT { get; set; }
[FieldOrder(29)]
public System.DateTime creation_date { get; set; }
[FieldOrder(30)]
public Nullable<System.DateTime> Inactive_date { get; set; }
[FieldOrder(31)]
public int status { get; set; }
}

Find Unique count on field using LINQ

I am trying to determine the Distinct count for a particular field in a collection of objects.
private static RemittanceCenterBatchSummaryListModel SummarizeFields(RemittanceCenterSummaryListModel remittanceCenterSummaryListModel)
{
var result = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecord.GroupBy(x => new{x.FileId, x.SourceFileName, x.BatchCode, x.BatchType})
.Select(x => new RemittanceCenterBatchSummarizedModel()
{
FileId = x.Key.FileId,
SourceFileName = x.Key.SourceFileName,
BatchCode = x.Key.BatchCode,
BatchType = x.Key.BatchType,
DetailRecordCountAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Adc),
DetailRecordCountNotAdc = x.Count(y => y.BillingSystemCode == BillingSystemCode.Exd),
AmountAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Adc).Sum(y => y.PaymentAmount),
AmountNotAdc = x.Where(y => y.BillingSystemCode == BillingSystemCode.Exd).Sum(y => y.PaymentAmount),
UniqueFileCount = x.Select(y => x.Key.FileId).Distinct().Count()
});
return CreateSummaryListModel(result);
}
Input entities:
public class RemittanceCenterSummaryListModel
{
public RemittanceCenterSummaryListModel()
{
this.RemittanceBatchSummaryRecord = new List<RemittanceBatchProcessingModel>();
}
public List<RemittanceBatchProcessingModel> RemittanceBatchSummaryRecord { get; private set; }
}
public class RemittanceCenterBatchSummarizedModel
{
public string FileId { get; set; }
public string SourceFileName { get; set; }
public string BatchCode { get; set; }
public string BatchType { get; set; }
public int DetailRecordCountAdc { get; set; }
public int DetailRecordCountNotAdc { get; set; }
public int DetailRecordCountTotal { get; set; }
public decimal AmountAdc { get; set; }
public decimal AmountNotAdc { get; set; }
public decimal AmountTotal { get; set; }
public BillingSystemCode BillingSystemCode { get; set; }
public int UniqueFileCount { get; set; }
}
private static RemittanceCenterBatchSummaryListModel CreateSummaryListModel(IEnumerable<RemittanceCenterBatchSummarizedModel> summaryModels)
{
var summaryModelList = new RemittanceCenterBatchSummaryListModel();
foreach (var summaryRec in summaryModels)
{
var summaryModel = new RemittanceCenterBatchSummarizedModel
{
FileId = summaryRec.FileId,
SourceFileName = summaryRec.SourceFileName,
BatchCode = summaryRec.BatchCode,
BatchType = summaryRec.BatchType,
DetailRecordCountAdc = summaryRec.DetailRecordCountAdc,
DetailRecordCountNotAdc = summaryRec.DetailRecordCountNotAdc,
AmountAdc = summaryRec.AmountAdc,
AmountNotAdc = summaryRec.AmountNotAdc,
UniqueFileCount = summaryRec.UniqueFileCount
};
summaryModelList.RemittanceBatchSummary.Add(summaryModel);
}
return summaryModelList;
}
Example input records:
Record1:
FileId: '123'
SourceFileName: 'test.file.txt'
BatchCode: 'aaa'
BatchType: 'scanned'
PaymentAmount: '50.00'
BillingSystemCode: 'Adc'
Record1:
FileId: '1234'
SourceFileName: 'test.file2.txt'
BatchCode: 'aab'
BatchType: 'scanned'
PaymentAmount: '52.00'
BillingSystemCode: 'Adc'
ActualOuput for UniqueFileCount Field:
UniqueFileCount = 1
ExpectedOutput results for UniqueFileCount Field:
UniqueFileCount = 2
What am I doing wrong?
It sounds like you want the distinct count of FileId for the entire collection and not just for each group, which will always be 1 since FileId is one of the fields you group on. If that is the case then you can just calculate that count first
int distinctFileIds = remittanceCenterSummaryListModel.RemittanceBatchSummaryRecor‌​d
.Select(x => x.FileId)
.Distinct()
.Count();
Then use that in your Linq query
UniqueFileCount = distinctFileIds

Categories