SQL:基于多个过滤器的多个where子句

本文关键字:where 子句 过滤器 于多个 SQL | 更新日期: 2023-09-27 17:55:45

如何编写具有嵌套过滤器的SQL查询。

信息:2个搜索过滤器

第一个过滤器:ID、名称、日期
第二个过滤器:取决于第一个,对于 Id:精确,范围;对于名称:精确,喜欢;对于日期:精确,范围。

在 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?

SQL:基于多个过滤器的多个where子句

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中添加参数。