select distinct out of three column connectiontable - sql

I have a ef connection table with 3 columns in it. I want to select distinct value out of two of them.
I want to select distinct rows orderby ResourceId and MetaDataId.
So i want it to return row (1, 3 and 4) in this case.
Ive tried this:
ctx.ResourceMetas.Where(a => a.ResourceId == resourceid).Distinct()});
But obviously this gets the distinct values out of all three. Can i somehow choose to get distinct out of just the two?

You may group by your distinct values and then get the max or min of the leftovers.
In your case that you only have one more field you could do it like:
ctx.ResourceMetas
.GroupBy(x=>new{x.ResourceId, x.MetaDataId})
.Select
(
x=>new
{
MetaListId = x.Min(m=>m.MetaListId ),
ResourceId = x.Key.ResourceId,
MetaDataId = x.Key.MetaDataId
}
)
.Where(a => a.ResourceId == resourceid)
But in a scenario that you would like the distinct values of 2 fields out of more than three then you would have to do it like:
ctx.ResourceMetas
.GroupBy(x=>new{x.ResourceId, x.MetaDataId})
.Select
(
x=>new
{
MetaListId = x.Where(i=>i.MetaListId == x.Min(m=>m.MetaListId)).FirstOrDefault().MetaListId ,
OtherField = x.Where(i=>i.MetaListId == x.Min(m=>m.MetaListId)).FirstOrDefault().OtherField ,
ResourceId = x.Key.ResourceId,
MetaDataId = x.Key.MetaDataId
}
)
.Where(a => a.ResourceId == resourceid)

Related

How can convert SQL to lambda or LINQ

How can I convert below SQL to lambda or LINQ?
with cte
as (select * from test1
union all
select * from test2)
select * from cte
union all
select sum(columnA),sum(columnB),sum(columnC) from cte
In Linq UNION ALL is .Concat(), so:
var cte = test1.Concat(test2);
var sums = new MyModel
{
columnA = cte.Sum(c => c.columnA),
columnB = cte.Sum(c => c.columnB),
columnC = cte.Sum(c => c.columnC),
}
return cte.Concat(IEnumerable.Repeat(sums, 1));
You must remember that test1 and test2 must be type MyModel and MyModel contains only columnA, columnB and columnC.
I put two tables together in one datagridvie but in the last row of datagridview I need the total for both tables in the country, I can do one row in total for one table and another row for the other table I also don't need it, like I can only have one line with the total of both tables.
DataContex db = new DataContex();
var query = (
from v1 in db.View1
where shf.Date >= dpDate.Value && shf.Date <= dpDate1.Value
select new
{
v1.Name,
v1.Date,
v1.Quality,
v1.Rat,
v1.Total
}
).Concat
(
from v2 in db.View2
where f.Date >= dpDate.Value && f.Date <= dpDate1.Value
select new
{
v2.Name,
v2.Date,
v2.Quality,
v2.Rat,
v2.Total
}
).Concat
(from View2 in
(from v2 in db.View2
where v2.Date >= dpDate.Value && sh.Date <= dpDate1.Value
select new
{
v2.Name,
v2.Date,
v2.Quality,
v2.Rate,
v2.Total
})
group v2 by new { v2.NRFA } into g
select new
{
Name = "Total:",
Date = dpDate1.Value,
Quality = (decimal?)g.Sum(p => p.Quality),
Rate = (decimal?)g.Sum(p => p.Rate),
Total = (decimal?)g.Sum(p => p.Total)
}
);
Blockquote

SQL lambda output not correct using nested select

I have 2 tables, Terms and Site_Program_Term:
Terms columns: Id, SiteId, Name, IsHoliday, DateStart, DateEnd, Year, IsActive
Site_Program_Term columns: Id, ProgName, SiteId, TermId, Year
Using the above 2 tables, I need to display output with primarily below columns
Name, StartDate, EndDate, NumberOfPrograms
I am getting the desired output but the 'NumberOfPrograms' is not showing the correct values. It should give me a count of all the Programs for a set of particular Term, Year and Site.
Thanks in advance.
Below is the base code.
var terms = db.Terms.Where(t => t.SiteId == id && t.IsActive).ToList().Select(t => new
{
Id = t.Id,
SiteId = t.SiteId,
Name = t.Name,
IsHoliday = t.IsHoliday,
DateStart = t.DateStart,
DateEnd = t.DateEnd,
Year = t.Year,
PubProgram = (
db.Site_Program_Term
.Where (spt => spt.SiteId == id && spt.Year == t.Year)
.Select(s => s).Count()
),
}).OrderBy(n => n.DateStart).ToList();
It should give me a count of all the
Programs for a set of particular Term, Year and Site.
But your Where condition only includes Year and Site, but not the Term. So
.Where(spt => spt.SiteId == id && spt.Year == t.Year)
should actually be:
.Where(spt => spt.SiteId == id && spt.Year == t.Year && spt.TermId == t.Id)
Note that if you are by any chance using Entity Framework (Core) and you have properly configured navigation property on the Term class such as
public class Term
{
// ...
public List<Site_Program_Term> SiteProgramTerms { get; set; }
}
then you can rewrite your query as
var terms = db.Terms
.Where(t => t.SiteId == id && t.IsActive)
.Select(t => new
{
Id = t.Id,
SiteId = t.SiteId,
Name = t.Name,
IsHoliday = t.IsHoliday,
DateStart = t.DateStart,
DateEnd = t.DateEnd,
Year = t.Year,
PubProgram = t.SiteProgramTerms.Where(spt => spt.SiteId == id && spt.Year == t.Year).Count()
})
.OrderBy(n => n.DateStart)
.ToList();
Note that this time you don't need to include spt.TermId == t.Id condition, because SiteProgramTerms property contains only site program terms with TermId that matches the Id of the Term. Also note that the first .ToList() should be omitted, because it causes query to be sent to the SQL server as multiple SELECT queries (as opposed to just one SELECT when .ToList() is not present).

Losing Aliases when trying to group-by rows in linq sql query, how to group-by rows in this case

I am a newbie intern way over my head, I promise I have researched this thoroughly and tried many different things. The following linq query works, but I want to group rows by last and first name and then only show the rows that appear more than once. When I un-comment out the group by statement, all my aliases below become unrecognized and changing them to the actual db.table names doesn't help.
var query = from emps in db.Employees
join c in db.Cards on emps.SbiID equals c.SbiID
where c.StateID == 0 && c.CardNumberNumeric > 100000
//group emps by new {emps.Surname, emps.Name};
//orderby grp.Count() // something like 'where grp.Count > 1
select new
{
Surname = emps.Surname,
Name = emps.Name,
CorpID = emps.Identifier,
CardNum = c.CardNumber,
CostCenter = emps.EmployeeUserField.UF13,
Supervisor = (from e in db.Employees
where
e.Identifier.Equals(emps.EmployeeUserField.UF5)
select e.Surname).FirstOrDefault()
+ ", "
+ (from e in db.Employees
where e.Identifier.Equals(emps.EmployeeUserField.UF5)
select e.Name).FirstOrDefault(),
SupervisorID = emps.EmployeeUserField.UF5,
EmpCommence = emps.CommencementDateTime,
CardCommence = c.CommencementDateTime,
WorkPhone = emps.Telephone,
State = (from cf in db.ComboFields
from sp in db.StringProperties
where cf.ComboIndex.Equals(c.StateID)
&& cf.StringID.Equals(sp.StringID)
&& cf.TableName.Equals("Card")
&& cf.FieldName.Equals("StateID")
select sp.DefaultValue).FirstOrDefault()
};
this.tagsGridView.DataSource = query;
this.tagsGridView.DataBind();
I think the problem you're running into is that you're not flattening out your groups appropriately. For example:
var duplicateEmployees = db.Employees
.GroupBy(emp => emp, new EmployeeComparer())
.Where(grp => grp.Count() > 1)
.SelectMany(grp => grp.AsEnumerable());
var duplicateEmployeeInfo =
from emps in duplicateEmployees
join c in db.Cards on emps.SbiID equals c.SbiID
where c.StateID == 0 && c.CardNumberNumeric > 100000
select new
{
... what to select
};
With:
public class EmployeeComparer : IEqualityComparer<Employee>
{
public bool Equals(Employee x, Employee y)
{
return x.Surname == y.Surname && x.Name == y.Name;
}
public int GetHashCode(Employee obj)
{
unchecked { return (17 * obj.Surname.GetHashCode()) ^ (23 * obj.Name.GetHashCode()); }
}
}
This groups the employees by name, finds the groups that have a count > 1, then returns the elements of those groups. No guarantees on performance, but this should solve your issue.

Nested selects in LINQ expression, how to?

I don't know how to work with nested selects in LINQ.
How could I convert this SQl expression to LINQ?
Select i.ID, i.Impression,
(Select COUNT(ImpressionsId)
from DiaryImpressions
where DiaryPostsId = '2' AND ImpressionsId = i.ID) as Num from Impressions i
Seriously? DiaryPostsId is a string? Oh well...
from i in context.Impressions
select new {
i.ID,
i.Impressions,
Num = (from d in context.DiaryImpressions
where d.DiaryPostsId == "2"
&& d.ImpressionsId == i.ID
select d).Count()
}
from ...
select new {
i.Id,
i.Impression,
Count = context.DiaryImpressions.Count(d => d.DiaryPostsId == 2 && d.ImpressionsId == i.Id)
}
If you map your objects properly, you can use child relations directly:
Count = i.DiaryImpressions.Count(d => d.DiaryPostsId == 2)

Need Linq translation for the following SQL Query

select colId,
colTaskType,
MaxID
from tblTaskType
join (
select tblCheckList.colTaskTypeID,
max(colItemNumber) MaxID
from tblCheckList
group by colTaskTypeID
) x on coltaskTypeID = tblTaskType.colID
Assuming you are using linq-to-sql and have the two tables in a datacontext.
The more or less exact translation would be:
var maxChecks = from checks in DataContext.tblChecklist
group checks by checks.colTaskTypeID into g
select new { colTaskTypeID, max = g.Group.Max(x => x.colItemNumber) };
var result = from t in DataContext.tblTaskType
join c in maxChecks on t.colTaskTypeID equals c.colTaskTypeID
select new { t.colId, t.colTaskTypeID, c.max };
But you could try:
var result = from t in DataContext.tblTaskType
select new {
t.colId,
t.colTaskTypeID,
Max = (from c in DataContext.tblChecklist
where c.colTaskTypeID == t.colTaskTypeID
select c.colItemNumber).Max() };