Selecting multiple columns from each row and removing duplicates - c#

Say I have a table with the following structure:
- Id
- Phone1
- Phone2
- Address
This table has multiple records.
What's the best way, using linq to SQL, of selecting all the phone numbers (from columns "Phone1" and "Phone2") in each row, and also removing repeated values.
I've tried something like but I can only get one column (Phone1) in each row:
var listOfResults = (from x in table
select x.Select(z => z.Phone1).Distinct()
).ToList();
Many thanks!

You can do this:
var listOfResults = (from x in table
select new
{
Phone1 = x.Phone1,
Phone2 = x.Phone2
}).Distinct();
or use groupby:
var listOfResults = (from x in table
group x by new { x.Phone1,x.Phone2 } into g
select new
{
Phone1 = g.Key.Phone1,
Phone2 = g.Key.Phone2
});
UPDATE:
var listOfResults = (from x in table
select new[]
{
new { Phone = x.Phone1 },
new { Phone = x.Phone2}
}).SelectMany(x=>x).Distinct();

var listOfPhone1 = (from x in table select x.Select(z => z.Phone1);
var listOfPhone2 = (from x in table select x.Select(z => z.Phone2);
var listOfResults = (listOfPhone1.AddRange(listOfPhone2)).Distinct();

You could have a look at the MoreLinq library found here. They have a function called DistinctBy which should solve your problem.

I don't know if this works with Linq-to-SQL, but with Linq-to-Object I would do it this way:
var unified = addresses.SelectMany(Row => new[] { new { Row, Phone = Row.Phone1 }, new { Row, Phone = Row.Phone2 } })
.Distinct(entry => entry.Phone)
.Select(entry => entry.Row);

Related

convert SQL to LINQ or imporve my query please

I am trying to convert sql to lambda or LINQ but can't simplified yet,
I managed to do it two different lambda but i want it a single query.
SQL query is this :
SELECT PamID, MAX (MaxAmount)
FROM RebateTable
GROUP BY PamID
so far this is working but is there any better way.
var t = from r in RebateList
group r by r.PamID;
var x = from y in t
select new RebateMaxClass
{
PamId = y.Key,
TotalSale = y.Max(s => s.MaxAmount)
};
You could use this form:
RebateTable.GroupBy(r=>r.PamId).Select(s=>new RebateMaxClass
{
PamId = s.Key,
TotalSale = s.Max(y => y.MaxAmount)
};
The query look good. You could form a single query like this:
var t = from r in RebateList
group r by r.PamId into y
select new
{
PamId = y.Key,
TotalSale = y.Max(s => s.MaxAmount)
};
But this is not faster. The Query is extended and will ont be executed until is has to.
An alternative is forming the "new LinQ-Style":
var t2 = RebateList.GroupBy(g => g.PamId) // Do a Grouping
var t3 = t2.Select(s => new { PamId = s.Key, TotalSale = s.Max(m => m.MaxAmount) });

LINQ Query with GroupBy, MAX and Count

What could be the LINQ query for this SQL?
SELECT PartId, BSId,
COUNT(PartId), MAX(EffectiveDateUtc)
FROM PartCostConfig (NOLOCK)
GROUP BY PartId, BSId
HAVING COUNT(PartId) > 1
I am actually grouping by two columns and trying to retrieve max EffectiveDateUtc for each part.
This is what I could write. Stuck up on pulling the top record based on the date.
Also not sure, if this is a optimal one.
//Get all the parts which have more than ONE active record with the pat
//effective date and for the same BSId
var filters = (from p in configs
?.GroupBy(w => new
{
w.PartId,
w.BSId
})
?.Select(g => new
{
PartId = g.Key.PartId,
BSId = g.Key.BSId,
Count = g.Count()
})
?.Where(y => y.Count > 1)
select p)
?.Distinct()?.ToList();
var filteredData = (from p in configs
join f in filters on p.PartId equals f.PartId
select new Config
{
Id = p.Id,
PartId = p.PartId,
BSId = p.BSId,
//EffectiveDateUtc = MAX(??)
}).OrderByDescending(x => x.EffectiveDateUtc).GroupBy(g => new { g.PartId, g.BSId }).ToList();
NOTE: I need the top record (based on date) for each part. Was trying to see if I can avoid for loop.
The equivalent query would be:
var query =
from p in db.PartCostConfig
group p by new { p.PartId, p.BSId } into g
let count = g.Count()
where count > 1
select new
{
g.Key.PartId,
g.Key.BSId,
Count = count,
EffectiveDate = g.Max(x => x.EffectiveDateUtc),
};
If I understand well, you are trying to achieve something like this:
var query=configs.GroupBy(w => new{ w.PartId, w.BSId})
.Where(g=>g.Count()>1)
.Select(g=>new
{
g.Key.PartId,
g.Key.BSId,
Count = g.Count(),
EffectiveDate = g.Max(x => x.EffectiveDateUtc)
});

How to filter a list based on 2 properties?

I have a list in my code that I need to filter through and return specific rows based on two criteria. The List in question is a list of models from a database. There are two ID properties on each model, one is the ID from the data table and is unique, the other is an ID we use to identify groups and can repeat. We'll call them ID and GroupID. Basically, I want the resulting list to have only one of each GroupID, and it should be the one with the highest (numerically speaking) ID. For example:
Input:
List<MyModel> modelList = new List<MyModel>
modelList[0].ID = 1 modelList[0].GroupID = 5
modelList[1].ID = 2 modelList[1].GroupID = 5
modelList[2].ID = 3 modelList[2].GroupID = 6
modelList[3].ID = 4 modelList[3].GroupID = 6
Desired Output:
Models at indexes 1 and 3.
Using LINQ:
var items = (from model in modelList
group model by model.GroupID into modelGroup
select modelGroup.Max(i => i.ID)).ToList();
What you have to do here is first order the modelList by ID and then GroupBy the list items by GroupID, then pull the item with max Id value.
var result = modelList.OrderByDescending(x => x.ID).GroupBy(x => x.GroupID).Select(x => x.First());
the above query will give you the result.
This is your solution:
var myData = models.GroupBy(model => model.GroupId)
.Select(group => group.OrderByDescending(model => model.Id).First());
Or you could also do this:
var myData = models.GroupBy(model => model.GroupId)
.Select(group => group.First(model => model.Id == group.Max(model1 => model1.Id)));
For fun, here's a fiddle.
You can try to use GroupBy.
var q = modelList.GroupBy(x => x.GroupID, x => x,
(key, g) => new {
GroupID = key,
Id = g.Max(c => c.ID)
});
This should group all your elements by GroupId and select Max ID in one of that groups.
Try this code:
List<MyModel> modelList = new List<MyModel>();
modelList.Add(new MyModel());
modelList.Add(new MyModel());
modelList.Add(new MyModel());
modelList.Add(new MyModel());
modelList[0].ID = 1; modelList[0].GroupID = 5;
modelList[1].ID = 2; modelList[1].GroupID = 5;
modelList[2].ID = 3; modelList[2].GroupID = 6;
modelList[3].ID = 4; modelList[3].GroupID = 6;
var list = from ml in modelList group ml by ml.ID into r select new { ID = r.Key, MaxGroupID = r.Max() };
this might help you
modelList.GroupBy(model => model.GroupId, g => g.Id).Select(item => item.Max())
var newModelList = modelList.GroupBy(ml => ml.GroupID)
.Select(g => new MyModel
{
ID = g.OrderByDescending(x => x.ID).First().ID,
GroupID = g.Key
}).ToList();
Details
1) GroupBy then Select to get distinct items over GroupID.
2) First() after OrderByDescending to get highest ID.
3) new MyModel in Select is just to be explicit about the projection.

convert sql to linq with two tables

select ind.desc,ind.number
from int_goals_df idd, goals_df ind
where idd.dld_number = 123456
and ind.number = idd.ind_number
and ind.categorie = 2
order by follownumber
I'm having a hard time translating this to linq since it is using two tables.
I've currently solved this now imperatively with a foreach loop but not happy with it..
I'm trying to get a list of goals_df that matches with a list of int_goals_df.
Any tips would be greatly appreciated ! Thank you !
EDIT - here is the code I'm using:
//get current GoalDefinitions by selected Goal
var currentGoalDefinition = MyAppAppContext.MyAppAppContextInstance.MyAppContext.GoalDefinitions.FirstOrDefault(
d => d.DLD_GoalDFID == interv.Goal.DLD_GoalenDFID);
// get current intervGoalDefinitions by GoalDefinition
var currentintervGoalDefinitions = MyAppAppContext.MyAppAppContextInstance.MyAppContext.intervGoalDefinitions.Where(
idd => idd.DLD_GoalDFID == currentGoalDefinition.DLD_GoalDFID).OrderBy(idd => idd.IDD_VolgNummer);
intervDefinitionCollection = new ObservableCollection<intervDefinition>(MyAppAppContext.MyAppAppContextInstance.MyAppContext.intervDefinitions.Where(i => i.IND_Categorie == intCategorie));
// filter intervGoalDefinitions by intervDefinitions
var intervDefinitionCollectionTemp = new ObservableCollection<intervDefinition>();
foreach (var currentintervGoalDefinity in currentintervGoalDefinitions)
{
var foundintervGoalDefinitySorted = intervDefinitionCollection.FirstOrDefault(
i => i.IND_intervDFID == currentintervGoalDefinity.IND_intervDFID);
if (foundintervGoalDefinitySorted != null)
intervDefinitionCollectionTemp.Add(foundintervGoalDefinitySorted);
}
intervDefinitionCollection = intervDefinitionCollectionTemp;
assuming NHibernate as ORM and int_goal is a subclass of goal
var results = from idd in session.Query<IntGoals>()
where idd.DlDNumber = 123456 && idd.Category.Id == 2
orderby idd.FollowNumber
select new { idd.Description, idd.Number };
context.int_goals_df.Join(context.goals_df, x => x.ind_number, x => x.number,
(x, y) => new
{
idd = x,
ind = y
})
.Where(x => x.idd.dld_number = 123456 && x.ind.categorie = 2)
.OrderBy(x => x.idd.follownumber)
.Select(x => new
{
x.ind.desc,
x.ind.number
});
quick go - think you need the join
var results = from idd in session.Query<int_goals_df>()
join ind in session.Query<goals_df>()
on idd.ind_number equals ind.ind_number
where idd.DlDNumber = 123456 && idd.Category.Id == 2
orderby idd.FollowNumber
select new { idd.Description, idd.Number };
I tend to use the sql syntax without implicit joins
/*Fields*/
SELECT ind.desc, ind.number
/*Tables*/
FROM int_goals_df idd
INNER JOIN goals_df ind
ON ind.number = idd.ind_number
/*Conditions*/
WHERE idd.dld_number = 123456
AND ind.categorie = 2
/*Order/Grouping*/
ORDER BY follownumber
You can see from Chris's answer this translates more easily to linq.

Select Min and Max LINQ

select description, min(date), max(date), sum(value1), sum(value2) from table
where description = 'Axxx' and filter = 'L'
group by description
How to perform this query using Linq / C#?
Not tested, but the following should work:
table
.Where(x=>x.description=="Axxx" && x.filter=="L")
.GroupBy(x=>x.description)
.Select(x=>new {
description=x.Key,
mindate=x.Min(z=>z.date),
maxdate=x.Max(z=>z.date),
sumvalue1=x.Sum(z=>z.value1),
sumvalue2=x.Sum(z=>z.value2)
});
something like this should work. not tested
var q = from b in table
group b by b.Owner into g
where description = 'Axxx'
select new
{
description = g.description ,
date = g.min(),
date = g.max(),
value1= g.Sum(item => item.value1),
value2= g.Sum(item => item.value2),
};
That should work
var q = from s in db.table
where description = 'Axxx' and filter = 'L'
group s by s.description into g
select new {YourDescription = g.description, MaxDate = g.Max(s => s.date) }
That answer may help, too .. here

Categories

Resources