[英]SQL to LINQ to get all records that match all values
如何将此查询转换为linq c#代码:
SELECT k1.Ad_Id FROM KeywordAdCategories k1, KeywordAdCategories k2
WHERE k1.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'ALFA')
AND k2.Keyword_Id = (SELECT Id FROM keywords WHERE name = '145')
AND k1.Ad_Id = k2.Ad_Id
ideia是基于可以为N的关键字数量构建动态查询(在示例中它们是2:ALFA和145)
谢谢
编辑:
KeywordAdCategory模型:
public class KeywordAdCategory
{
[Key]
[Column("Keyword_Id", Order = 0)]
public int Keyword_Id { get; set; }
[Key]
[Column("Ad_Id", Order = 1)]
public int Ad_Id { get; set; }
[Key]
[Column("Category_Id", Order = 2)]
public int Category_Id { get; set; }
}
关键字模型:
public class Keyword
{
// Primary properties
public int Id { get; set; }
public string Name { get; set; }
}
如果我有5个关键字,我会得到:
SELECT k1.Ad_Id FROM KeywordAdCategories k1, KeywordAdCategories k2, KeywordAdCategories k3, KeywordAdCategories k4, KeywordAdCategories k5
WHERE k1.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD1')
AND k2.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD2')
AND k1.Ad_Id = k2.Ad_Id
AND k3.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD3')
AND k2.Ad_Id = k3.Ad_Id
AND k4.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD4')
AND k3.Ad_Id = k4.Ad_Id
AND k5.Keyword_Id = (SELECT Id FROM keywords WHERE name = 'KEYWORD5')
AND k4.Ad_Id = k5.Ad_Id
当我第一次看到它时,我觉得这有点棘手,所以我可能在想它。 但这是一个我认为适合你的解决方案:
var keywordList = new List<string>();
keywordList.Add("ALFA");
keywordList.Add("145");
var results = KeywordAdCategories.Select (kac => kac.Ad_Id).Distinct()
.Select (a =>
new
{
AdId=a,
Keywords=KeywordAdCategories.Where(kac => kac.Ad_Id == a).Select(kac => kac.Keyword_Id)
})
.Where(ac => ac.Keywords.Intersect(Keywords.Where(kw => keywordList.Contains(kw.Name)).Select (kw => kw.Id)).Count() == keywordList.Count())
.Select (ac => ac.AdId);
现在解释一下我在这里做了什么。 首先,我想从所有可能的广告ID开始,所以我们有这条线:
KeywordAdCategories.Select (kac => kac.Ad_Id).Distinct()
当然,这可能更容易从广告表中的不同选择中检索出来,但我尝试只使用您定义的内容。
接下来,我将每个广告ID及其相关的关键字集合选择为匿名类型对象列表:
.Select (a =>
new
{
AdId=a,
Keywords=KeywordAdCategories.Where(kac => kac.Ad_Id == a).Select(kac => kac.Keyword_Id)
})
接下来,我将结果过滤为仅包含与我们的关键字列表相交的关键字集合的对象,并且与关键字列表具有相同数量的结果元素。
.Where(ac => ac.Keywords.Intersect(Keywords.Where(kw => keywordList.Contains(kw.Name)).Select (kw => kw.Id)).Count() == keywordList.Count())
最后我选择了广告ID的结果
.Select (ac => ac.AdId);
如果你有兴趣,这里是emmited sql
-- Region Parameters
DECLARE @p0 NVarChar(1000) = 'ALFA'
DECLARE @p1 NVarChar(1000) = '145'
DECLARE @p2 Int = 2
-- EndRegion
SELECT [t1].[Ad_Id]
FROM (
SELECT DISTINCT [t0].[Ad_Id]
FROM [KeywordAdCategories] AS [t0]
) AS [t1]
WHERE ((
SELECT COUNT(*)
FROM (
SELECT DISTINCT [t2].[Keyword_Id]
FROM [KeywordAdCategories] AS [t2]
WHERE (EXISTS(
SELECT NULL AS [EMPTY]
FROM [Keywords] AS [t3]
WHERE ([t2].[Keyword_Id] = [t3].[Id]) AND ([t3].[Name] IN (@p0, @p1))
)) AND ([t2].[Ad_Id] = [t1].[Ad_Id])
) AS [t4]
)) = @p2
我确信有更多优雅的方法来完成你想要做的事情,但我想看看我是否可以在一个linq查询中完成所有这些。 希望这可以帮助。
List<string> keywordnames = new List<string>();
// populate keywordsnames list
IQueryable<int> AdIds = from k in KeywordAdCategories
where
(from kw in Keywords where keywordnames.Contains(kw.name) select kw.id)
.Contains(k.keyword_id)
select k.Ad_Id;
要么
List<string> keywordnames = new List<string>();
// populate keywordsnames list
List<int> keywordnameids = (from kw in ctx.Keywords
where keywordnames.Contains(kw.name)
select kw.id).ToList();
List<int> AdIds = (from k in ctx.KeywordAdCategories
where keywordnameids.Contains(k.Keyword_Id)
select k.Ad_Id).ToList();
public static int GetAdId(string KeywordId)
{
var dbContext = new MyDbContext();
var result = (from k in in dbContext.KeywordAdCategories
where k.Keyword_Id == KeywordId
select k.Ad_Id).SingleOrDefault();
return result;
}
通过此方法运行所有关键字ID,您将获得相应的广告ID。 我建议您阅读LINQ。 一旦你了解它,这是一个很棒的工具,虽然起初看起来有点可怕,但它并不难学。 Pluralsight.com有很多很棒的视频,很容易掌握和学习:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.