c# - LINQ 查询 SQL HAVING CLAUSE

标签 c# asp.net-mvc linq-to-sql

[重写:31/01] 我遇到了这个问题,我试图在我使用 HAVING ... AND 的地方重新生成 SQL 查询。

下表显示了商店表 (ID) 和 Assets (A-F 是 Assets 的类型或名称)的简化 View 。 我的 View 向 Controller 发送一个名称列表(来自使用 MvcCheckBoxList 实现的复选框)。

enter image description here

我的查询结果应该是一个列表 ID,其中每个 ID 至少包含一个所选的每个 Assets 名称。

例子 - 名称列表仅包括 A 和 B 返回 ID { 4 } - 名称列表 = A、C 和 E 返回 ID { 4 和 6 }

SQL 查询 之前我使用循环创建了一个文本字符串,它将后续的 AND 子句连接在一起并作为 SQL connectionString 传递。

上面的示例 1 看起来像这样:

SELECT * FROM Stores S, ....(all other columns required)
LEFT JOIN Assets A ON S.ID == A.SID
WHERE (DATE ....)
HAVING (count(case when A.Name == "A" then 1 else NULL end) > 0) AND (count(case when A.Name == "B" then 1 else NULL end) > 0)
GROUP BY S.ID;

这是我需要复制的 HAVING .. AND。

Linq 查询 这个我试过了

stores = (from s in stores 
join a in db.Assets on s.ID equals a.StoreID
where (postedTillNames.Contains(a.Name)).Distinct().ToList();

但这会返回任何具有任何名称的商店。 postedTillNames 是从 Model 中的 View 回发的,是一个字符串数组。

使用for循环的解决方案

所以我找到了一个非 Linq 的解决方法,我将暂时使用它,但如果可能的话我想使用干净的 linq(并且也学习一些东西 ;-):

List<Store> tillStores = new List<Store>();
foreach (var s in stores)
{
    bool r = true;

    for (int c = 0; c < postedTillNames.Count(); c++)
    {
        r = (s.Assets.Where(a => a.Name == postedTillNames[c]).Count() > 0) ? true : false;
        if (!r) break;
    }

    if (r) tillStores.Add(s);
}

再次感谢您到目前为止的帖子和评论。

问候 克雷格


更新:我已经完全重写了问题,所以请从顶部阅读

最佳答案

使用下面的类结构:

class Store
{
    public int ID { get; set; }
    public string Name { get; set; }
}
class Asset
{
    public int StoreID { get; set; }
    public string Name { get; set; }        
}

和数据:

List<Store> Stores = new List<Store>()
{
   new Store { ID = 1, Name = "First"},
   new Store { ID = 2, Name = "Second"},
   new Store { ID = 3, Name = "Third"},
   new Store { ID = 4, Name = "Fourth"},
   new Store { ID = 5, Name = "Fifth"},
   new Store { ID = 6, Name = "Sixth"}
};

List<Asset> Assets = new List<Asset>()
{
    new Asset { StoreID = 1, Name = "B"},
    new Asset { StoreID = 1, Name = "B"},
    new Asset { StoreID = 1, Name = "F"},
    new Asset { StoreID = 1, Name = "F"},
    new Asset { StoreID = 2, Name = "A"},
    new Asset { StoreID = 2, Name = "A"},
    new Asset { StoreID = 2, Name = "C"},
    new Asset { StoreID = 2, Name = "D"},
    new Asset { StoreID = 3, Name = "B"},
    new Asset { StoreID = 3, Name = "B"},
    new Asset { StoreID = 3, Name = "B"},
    new Asset { StoreID = 4, Name = "A"},
    new Asset { StoreID = 4, Name = "B"},
    new Asset { StoreID = 4, Name = "C"},
    new Asset { StoreID = 4, Name = "C"},
    new Asset { StoreID = 4, Name = "D"},
    new Asset { StoreID = 4, Name = "D"},
    new Asset { StoreID = 4, Name = "D"},
    new Asset { StoreID = 4, Name = "E"},
    new Asset { StoreID = 4, Name = "F"},
    new Asset { StoreID = 5, Name = "D"},
    new Asset { StoreID = 6, Name = "A"},
    new Asset { StoreID = 6, Name = "A"},
    new Asset { StoreID = 6, Name = "C"},
    new Asset { StoreID = 6, Name = "E"}
  };

作为存储在数据库中的真实表和数据的模型,您可以使用以下 Linq 查询来获取您想要的内容:

string[] postedTillNames = { "A", "C", "E"};

var result = (from s in Stores
             join a in Assets on s.ID equals a.StoreID
             group new { A = a, S = s } by a.StoreID into assetsGroup
             where !postedTillNames.Any(p => !assetsGroup.Select(g => g.A.Name)
                                                         .Contains(p))
             select assetsGroup.First().S).ToList();

以上查询返回 List<Store>包含 ID = 4、6 的商店的对象。

关于c# - LINQ 查询 SQL HAVING CLAUSE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28244840/

相关文章:

c# - LINQ 动态分组

MVC 布局中的 CSS 命名最佳实践

c# - 禁用 MvcSiteMapProvider 缓存

c# - 大型 WCF Web 服务请求因 (400) HTTP Bad Request 而失败

c# - 可移植类库 : navigate to xaml page

linq - linq中的连接问题

c# - 使用 LINQ 根据字符串列表选择多个记录

asp.net-mvc - MVC3、 Razor 、Html.TextAreaFor() : adjust height to fit contents

asp.net-mvc - mvc4 webapi自定义特定类型的json序列化器

c# - LINQ to SQL Select Distinct by Multiple Columns 并返回整个实体