开发者

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 ()
         }
   )
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜