4

如何将此查询转换为 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

想法是根据可以为 N 的关键字的数量构建一个动态查询(在示例中它们是 2:ALFA 和 145)

谢谢

编辑:

关键字广告类别模型:

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
4

3 回答 3

1

我第一次看到它时认为这有点棘手,所以我可能想多了。但这里有一个我相信对你有用的解决方案:

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 查询中完成这一切。希望这可以帮助。

于 2013-02-06T22:25:42.267 回答
0
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();
于 2013-02-06T19:18:38.337 回答
-1
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 有很多很棒的视频,很容易掌握和学习:)

于 2013-02-06T19:13:15.297 回答