WHERE 子句中的多个过滤器






1.63/5 (8投票s)
2005年5月2日
6分钟阅读

52145
如何在 SQL 语句的 WHERE 子句中编写多个过滤器。
WHERE 子句中的多个过滤器
引言
有时我需要开发一个报表或一些显示数据的东西,但之前用户可以应用多个筛选器,以便查看想要查找的信息。
我一如既往地设计了带有筛选器的用户界面,然后将筛选器传递到不同的层,最后,它们到达了一个存储过程,该存储过程进行查询。
它返回数据,仅此而已。
我曾多次听到一些同事说,他们必须显示应用了多个筛选器的数据,但最终在存储过程中,他们除了通过构建字符串然后使用 EXEC sql 命令执行它,或者制作多个 SELECT 语句之外,找不到其他方法来构建查询。
示例
以 pubs 数据库为例说明这种情况。
我们必须显示属于某个出版商或拥有特定职位的员工。
用户界面如下所示
您可以通过选择职位或(所有职位)来筛选职位,也可以通过选择出版商或(所有出版商)来筛选出版商。
解决查询的存储过程大致如下所示
制作多个 SELECT 语句
CREATE PROCEDURE dbo.GetEmployeesFiltered1
(
@JobFilter int ,
@PublisherFilter int
)
AS
begin
declare @FilterByJob bit
declare @FilterByPub bit
if @JobFilter > 0
begin
select @FilterByJob = 1
end
else
begin
select @FilterByJob = 0
end
if @PublisherFilter > 0
begin
select @FilterByPub = 1
end
else
begin
select @FilterByPub = 0
end
if @FilterByJob=1
BEGIN
if @FilterByPub=1
BEGIN
--按职位和出版商筛选
SELECT jobs.job_desc AS Expr1, publishers.pub_name AS Expr2, employee.*
FROM jobs INNER JOIN
employee ON jobs.job_id = employee.job_id INNER JOIN
publishers ON employee.pub_id = publishers.pub_id
WHERE
publishers.pub_id = @PublisherFilter
或者
jobs.job_id = @JobFilter
END
else
--按职位筛选
BEGIN
SELECT jobs.job_desc AS Expr1, publishers.pub_name AS Expr2, employee.*
FROM jobs INNER JOIN
employee ON jobs.job_id = employee.job_id INNER JOIN
publishers ON employee.pub_id = publishers.pub_id
WHERE
jobs.job_id = @JobFilter
END
END
else
--不按职位筛选
BEGIN
if @FilterByPub=1
BEGIN
SELECT jobs.job_desc AS Expr1, publishers.pub_name AS Expr2, employee.*
FROM jobs INNER JOIN
employee ON jobs.job_id = employee.job_id INNER JOIN
publishers ON employee.pub_id = publishers.pub_id
WHERE
publishers.pub_id = @PublisherFilter
END
else
--不按出版商筛选
BEGIN
SELECT jobs.job_desc AS Expr1, publishers.pub_name AS Expr2, employee.*
FROM jobs INNER JOIN
employee ON jobs.job_id = employee.job_id INNER JOIN
publishers ON employee.pub_id = publishers.pub_id
END
END
end
这类过程的问题在于维护起来很麻烦,您必须记住为所有选项/筛选器维护 SELECT 语句。
所以可以用这种方式解决
通过 EXEC 命令执行构建的 SELECT 语句
CREATE PROCEDURE dbo.GetEmployeesFiltered2
(
@JobFilter int ,
@PublisherFilter int
)
AS
begin
declare @FilterByJob bit
declare @FilterByPub bit
if @JobFilter > 0
begin
select @FilterByJob = 1
end
else
begin
select @FilterByJob = 0
end
if @PublisherFilter > 0
begin
select @FilterByPub = 1
end
else
begin
select @FilterByPub = 0
end
declare @mySentece varchar (1000)
declare @myFilter varchar (1000)
select @mySentece = 'SELECT jobs.job_desc AS Expr1, publishers.pub_name AS Expr2, employee.*
FROM jobs INNER JOIN
employee ON jobs.job_id = employee.job_id INNER JOIN
publishers ON employee.pub_id = publishers.pub_id'
if @FilterByJob=1
BEGIN
if @FilterByPub=1
BEGIN
--按职位和出版商筛选
SELECT @myFilter = 'publishers.pub_id = ' + @PublisherFilter + '
OR
jobs.job_id = ' + @JobFilter
END
else
--按职位筛选
BEGIN
SELECT @myFilter = 'jobs.job_id = ' + @JobFilter
END
END
else
--不按职位筛选
BEGIN
if @FilterByPub=1
BEGIN
SELECT @myFilter = 'publishers.pub_id = ' + @PublisherFilter
END
else
--不按出版商筛选
BEGIN
SELECT @myFilter = ''
END
END
end
if @myFilter = ''
begin
exec ( @mySentece )
end
else
begin
exec ( @mySentece + ' WHERE ' + @myFilter )
end
这里解决了为所有选项/筛选器维护 SELECT 语句的问题,但它存在 SQL Server 必须在每次执行时编译存储过程的问题。
多重筛选 SELECT 语句
这就是我提出的带有 多个筛选器的查询解决方案
CREATE PROCEDURE dbo.GetEmployeesFiltered3
(
@JobFilter int ,
@PublisherFilter int
)
AS
begin
declare @FilterByJob bit
declare @FilterByPub bit
if @JobFilter > 0
begin
select @FilterByJob = 1
end
else
begin
select @FilterByJob = 0
end
if @PublisherFilter > 0
begin
select @FilterByPub = 1
end
else
begin
select @FilterByPub = 0
end
SELECT jobs.job_desc AS Expr1, publishers.pub_name AS Expr2, employee.*
FROM jobs INNER JOIN
employee ON jobs.job_id = employee.job_id INNER JOIN
publishers ON employee.pub_id = publishers.pub_id
WHERE
(@FilterByPub=1 AND publishers.pub_id = @PublisherFilter )
或者
(@FilterByJob=1 AND jobs.job_id = @JobFilter )
End
主要步骤是确定要“激活”哪些筛选器。当此指示器打开时,它将应用 WHERE 搜索条件。
这是在 WHERE 子句中构建多个筛选器的诀窍。
关于 fhunth
最近,我受雇于 Huddle Group (http://www.huddle.com.ar/) 担任 C# 高级开发人员
联系我:
访问我的博客:
http://msdevelopers.blogspot.com/