LINQ lambda syntax for SQL subquery + count(distinct on one column)
How would I write the following SQL query in lambda-notation LINQ?
select 'myString', count(distinct val)
from myChildTable
where mytable_id in (
select id
from myTable
where col1_int = 6
and col2_int between 1 and 366
and col3_str = 'myString'
)
For reference, the two tables in question are:
create table myTable (
id int primary key identity,
col1_int int not null,
col2_int int not null,
col3_str varchar(1024)
)
create table myChildTable (
id int primary key identity,
mytable_id int not null foreign key references myTable(id),
val varbi开发者_开发知识库nary(13) not null
)
This could possibly be shortened but I find it easier to read if broken up:
// list ids from table
var ids = myTable.Where(x => x.Col1Int == 6 && x.Col2Int >= 1 && x.Col2Int <= 366 && x.Col3Str == "myString").Select(x => x.Id).ToList();
// use in subquery for values (non-distinct)
var vals = myChildTable.Where(x => ids.Contains(x.Id)).Select(x => x.Val).ToList();
// project to distinct dictionary of value, count
var dict = vals.Distinct().ToDictionary(x => x, x => vals.Count(y => y == x));
This seems to work using classes like these:
class ParentEntity
{
public int Id { get; set; }
public int Col1Int { get; set; }
public int Col2Int { get; set; }
public string Col3Str { get; set; }
public ParentEntity(int id, int col1Int, int col2Int, string col3Str)
{
Id = id;
Col1Int = col1Int;
Col2Int = col2Int;
Col3Str = col3Str;
}
}
class ChildEntity
{
public int Id { get; set; }
public int ParentEntityId { get; set; }
public string Val { get; set; }
public ChildEntity(int id, int parentEntityId, string val)
{
Id = id;
ParentEntityId = parentEntityId;
Val = val;
}
}
This query should to it:
from c in MyChildTables
where MyTables.Any (mt => mt.Col1_int == 6 && mt.Col2_int >= 1 &&
mt.Col2_int <= 366 && mt.Col3_str == "myString" && mt.Id == c.Id)
group c by true into g
select new
{
Col1 = "myString",
Col2 = g.Select (x => x.Val).Distinct().Count ()
}
Or if you rather have it in Lambda-notation:
MyChildTables
.Where (
c =>
MyTables
.Any (
mt =>
(((((mt.Col1_int == 6) && (mt.Col2_int >= 1)) && (mt.Col2_int <= 366)) && (mt.Col3_str == "myString")) && (mt.Id == c.Id))
)
)
.GroupBy (c => True)
.Select (
g =>
new
{
Col1 = "myString",
Col2 = g.Select (x => x.Val).Distinct ().Count ()
}
)
精彩评论