linq查询过滤

时间:2017-01-09 17:12:59

标签: c# linq entity-framework-6

我有一张像这样的平面桌(称之为t1)

a1 b1 c1 v1 
a1 b1 c1 v2
a1 b1 c2 v4
a1 b1 c3 v3
a1 b1 c3 v4

假设我想按最后一列过滤,我会寻找v1。有没有办法编写linq查询,我也得到结果集中的第二行?基本上我想要所有c1的过滤器匹配v1或v2,即使只指定了v1?

c3相同。如果我想过滤v4,我想要在结果集中返回最后2行。

现在我正在绕过它,通过在我的控制器上进行另一个db调用来获取c1的所有值(如果c1是从过滤器查询中返回的),然后再将其发送到视图。

2 个答案:

答案 0 :(得分:2)

  

有没有办法编写linq查询...

如果我正确解释了问题,我相信以下代码块应该有效(假设您可以访问所有相关数据):

var filterText = "v4";
var filteredList = yourList.GroupBy(yourItem => yourItem.Third)
        .Where(groupedItem => groupedItem.Any(yourItem => yourItem.Fourth == filterText))
        .SelectMany(matchedItem => matchedItem).ToList()

鉴于" v4"作为过滤文本,此语句将返回

a1 b1 c2 v4
a1 b1 c3 v3
a1 b1 c3 v4

鉴于" v1"作为过滤文本,此语句将返回

a1 b1 c1 v1
a1 b1 c1 v2

可以找到一个工作示例here

解释

  

"我想要所有c1&s,其中过滤器匹配v1或v2偶数   虽然只指定了v1?"

这可以通过将数据分组显示为第三列(包含所有" c" s的列),然后返回包含具有匹配的行的所有组来轻松完成第四列(包含所有" v" s的列),然后展平该结果集,这样您就没有组列表。换句话说:

  1. 我首先使用ThirdGroupBy()对对象进行分组。
  2. 然后,Where()用于返回"任何"具有匹配的第四列的项目的组。
  3. 此时,由于我们有一个组列表(如果你调试语句,你会看到这个),我用SelectMany()展平了结果。
  4. 实施例

    我对您的数据集的解释:

    public class Foo
    {
        public string First { get; set; }
        public string Second { get; set; }
        public string Third { get; set; }
        public string Fourth { get; set; }
    }
    

    设置数据:

    var yourList = new List<Foo>()
    {
        new Foo(){First = "a1", Second="b1", Third="c1", Fourth="v1"},
        new Foo(){First = "a1", Second="b1", Third="c1", Fourth="v2"},
        new Foo(){First = "a1", Second="b1", Third="c2", Fourth="v4"},
        new Foo(){First = "a1", Second="b1", Third="c3", Fourth="v3"},
        new Foo(){First = "a1", Second="b1", Third="c3", Fourth="v4"}
    };
    

    过滤代码:

    var filterText = "v4";
    
    var filteredList = yourList.GroupBy(yourItem => yourItem.Third)
        .Where(groupedItem => groupedItem.Any(yourItem => yourItem.Fourth == filterText))
        .SelectMany(matchedItem => matchedItem).ToList();
    

答案 1 :(得分:2)

假设您有一个名为Table的表格,列A, B, C, Vdb是您的派生DbContext的实例,而v是变量持有搜索列V的标准。

以下几乎所有可能的LINQ查询都使用单个SQL查询生成所需的结果:

(A)使用GroupBy,过滤组并使用SelectMany展平结果(在@Joshua Miller答案中提到):

var queryA = db.Table
    .GroupBy(e => e.C)
    .Where(g => g.Any(e => e.C == v))
    .SelectMany(g => g);

(B)将自JoinWhere

一起使用
var queryB = db.Table
    .Join(db.Table.Where(e2 => e2.V == v), e1 => e1.C, e2 => e2.C, (e1, e2) => e1);

(C)使用复合键自连接:

var queryC = db.Table
    .Join(db.Table, e1 => new { e1.C, V = v }, e2 => new { e2.C, e2.V }, (e1, e2) => e1);

(D)将WhereAny条件一起使用:

var queryD = db.Table
    .Where(e1 => db.Table.Any(e2 => e2.C == e1.C && e2.V == v));

(E)使用Where Select + Contains条件(@juharr在评论中提到):

var queryE = db.Table
    .Where(e1 => db.Table.Where(e2 => e2.V == "v1").Select(e2 => e2.C).Contains(e1.C));

那么选择哪一个?

在LINQ to Objects中,(A),(B)和(C)具有相似的O(N)时间复杂度,而(D) 由于O(N ^ 2)时间复杂度,(E)不好。

在LINQ to Entities(EF6)中,图片略有不同:

(A)不好,因为它转化为涉及3次Table访问路径的可怕SQL。

(B)和(C)翻译为Table self INNER JOIN,实际上是同一个。

(D)和(E)使用EXISTS子句转换为同一个SQL查询。

因此,应该避免(A),其余的应该由现在的SQL查询优化器生成一个相同的执行计划,因此您选择哪一个应该是品味问题。您仍然应该查看执行计划并测量性能。