簡體   English   中英

如何從 linq 的查詢結果中排除?

[英]How to exclude from query's result in linq?

第一個查詢

第二個查詢

在第一張圖片中,我有第一個查詢的結果,突出顯示的部分表示將通過在第二個查詢上應用過濾器來排除的行,在第二張圖片中,我有查詢select * from exlusion_table的結果

我必須對第一個查詢進行更改以使其排除從第二個查詢中檢索到的項目

第一個查詢:

var u = from a in cx.VW_LIST
        where (a.PRJ == codPrj) && (a.DATE > date_ || a.DATE == null || date_ == null)
        && (x.Contains(a.CODE) || x.Count() == 0)
        select a)

第二個查詢:

var y = from esc in cx.EXCLUSION select esc

應修改第一個查詢以排除所有具有值 fcode = 第二個查詢的 fcode(在第二個查詢的 fscode = null 的情況下)或那個(fcode = 第二個查詢的 fcode && fscode = 第二個查詢的 fscode )

你可以使用任何()。 IE:

var u = from a in cx.VW_LIST
        where (a.PRJ == codPrj) 
           && (a.DATE > date_ || a.DATE == null || date_ == null)
           && (x.Contains(a.CODE) || x.Count() == 0)
           && (!cx.EXCLUSION.Any( y => x.fscode == y.fscode && x.fcode == y.fcode ))
        select a)

有兩種方法,一種是使用! ANY()過濾掉在其他列表中找到的記錄,這將編譯成WHERE NOT EXISTS(_exclusion_)過濾表達式

var excluded = cx.EXCLUSION.AsQueryable();

var query = from vw in cx.VW_LIST
            where vw.PRJ == codPrj
            where vw.DATE == null || date_ == null || vw.DATE > date_
            where !x.Any() || x.Contains(vw.CODE)
            where !excluded.Any(esc => vw.fcode == esc.fcode 
                                   && (esc.fscode == null || vw.fscode == esc.fscode))
            select vw;

var results = query.ToList();

棘手的元素是排除表中nullfscode ,它需要充當通配符匹配,或者否定fscode比較。

沒有必要將excluded的查詢拆分成它自己的查詢,我們可以直接引用cx.EXCLUSION表,它會產生完全相同的效果,這向您展示了一種用於構建 LINQ 查詢的封裝技術您可以輕松地增加排除查找的復雜性,而不會造成整個查詢的混亂。

您可能還會發現需要有條件地構建查詢,這就是 Fluent syntax 提供更模塊化方法的地方:

bool filterExcludedRecords = true;
...
var excluded = cx.EXCLUSION.AsQueryable();

var query = cx.VW_LIST.Where(vw => vw.PRJ == codPrj)
                      .Where(vw => vw.DATE == null || date_ == null || vw.DATE > date_)
                      .Where(vw => !x.Any() || x.Contains(vw.CODE));
if(filterExcludedRecords)
    query = query.Where(vw => !excluded.Any(esc => vw.fcode == esc.fcode 
                              && (esc.fscode == null || vw.fscode == esc.fscode)));

var results = query.ToList();

外部連接

另一種方法是在未找到排除匹配項的情況下使用LFET OUTER JOIN

var excluded = cx.EXCLUSION.AsQueryable();

var query = from vw in cx.VW_LIST
            where vw.PRJ == codPrj
            where vw.DATE == null || date_ == null || vw.DATE > date_
            where !x.Any() || x.Contains(vw.CODE)
            from esc in excluded.Where(e => vw.fcode == e.fcode 
                                            && (e.fscode == null || vw.fscode == e.fscode))
                                .DefaultIfEmpty()
            where esc.fscode == null
            select vw;

var results = query.ToList();

WHERE NOT EXISTS通常在性能方面更勝一籌, OUTER JOIN在未優化的表中或當排除列表中的行數非常少而主表中的行數非常大時,可能會提供更好的響應。

我包括這個查詢選項是為了完整性,眾所周知,您可以通過向查詢添加新from子句來創建簡單的外部聯接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM