簡體   English   中英

SQL:基於多個過濾器的多個Where子句

[英]SQL: Multiple Where Clause based on multiple filters

如何編寫具有嵌套過濾器的SQL查詢。

信息:2個搜索過濾器

第一個過濾器:Id,Name,Date
第二個過濾器:取決於第一個,對於Id:精確,范圍; for name:exact,like; 對於日期:確切,范圍。

在LINQ代碼中,它的完成類似於:

theList = somelistFromDb;
case filter1
   case "Id"
       if filter2 == "exact"
          theList.where(x => x == searchkey);
       else if filter 2 == "range"
          theList.where(x => x >= searchkey && x<=searchkey2);
   case "Name"
       if filter2 == "exact"
          theList.where(x => x == searchkey);
       else if filter2 == "like"
          theList.where(x => x.contains("searchkey));
...

如何將上述LINQ偽代碼轉換為SQL?

SELECT
...
WHERE
  (:filterParam='Id' AND <all the Id filter conditions> here)
OR
  (:filterParam='Name' AND <all the Name filter conditions> here)
select * from [Table] where 
((@filter1='Id') and 
  ((filter2='exact' and [Table].[Id]=@searchkey) OR
   (filter2='range' and [Table].[Id]>=@searchkey and [Table].[Id]<=@searchkey2) ))
OR
((@filter1='Name') and 
.....

編寫一個滿足或排除所有條件的TSQL查詢通常非常不理想 - 它會導致糟糕的查詢計划。 試圖在TSQL中做所有的想法是......有點難看 - TSQL根本不是一個很好的語言。

所以:我通常這樣做的方法是在C#中構建查詢,例如:

static void AppendFilter(StringBuilder filter, string clause)
{
    filter.Append(filter.Length == 0 ? " where " : " and ").Append(clause);
}

StringBuilder filter = new StringBuilder();
if(/* some condition */)
    AppendFilter(filter, "row.Foo = @foo");
if(/* some condition */)
    AppendFilter(filter, "row.Bar > @bar"); 
// ...
string tsql = "select * from SomeTable row" + filter.ToString();
// pack params, exec

這個:

  • 擴展到任意數量的過濾器
  • 為每個過濾器組合生成適當的TSQL,以獲得最佳查詢計划
  • 很容易維護

就個人而言,我也會使用dapper來執行,因為它具有內置的(基本)參數分析,允許簡單:

var rows = conn.Query<SomeType>(tsql, new { foo, bar, ... }).ToList();

(但它仍然只發送必要的參數)

但是,另一種方法是在每個if添加參數。

暫無
暫無

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

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