我有一张像这样的平面桌(称之为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是从过滤器查询中返回的),然后再将其发送到视图。
答案 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的列),然后展平该结果集,这样您就没有组列表。换句话说:
Third
按GroupBy()
对对象进行分组。Where()
用于返回"任何"具有匹配的第四列的项目的组。 SelectMany()
展平了结果。 我对您的数据集的解释:
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, V
,db
是您的派生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)将自Join
与Where
:
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)将Where
与Any
条件一起使用:
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查询优化器生成一个相同的执行计划,因此您选择哪一个应该是品味问题。您仍然应该查看执行计划并测量性能。