如何过滤表中的值,但仅当它有记录时?

时间:2012-01-18 01:49:04

标签: sql sql-server-2005 join filter

我有一张包含交易记录的表Tran

我有两个表Parameters1Parameters2,用于在从Tran表格中选择时过滤结果:

SELECT *  
FROM  
     Tran t JOIN  
     Parameters1 p1 ON T.code1 = p1.code1  
     Parameters2 p2 ON T.code2 = p2.code2  
WHERE p1.code1 is not null AND
      p2.code2 is not null

有时Parameters1Parameters2为空。

我想要的是仅当Parameters表有记录时才进行过滤。换句话说,如果Parameters1为空,请不要使用它来过滤,反之亦然。同样适用于Parameters2

我很难过。

4 个答案:

答案 0 :(得分:3)

您通常使用dynamic SQL执行此操作,因为使用静态SQL编写动态搜索条件通常是个hackish。如果您对这种方法感兴趣,我强烈推荐Erland Sommarskog的页面dynamic SQL for SQL Server 2005。他有一个很好的案例研究,里面有很多关于如何完全满足你所要求的示例代码。

1。设置

无论您使用动态SQL还是静态SQL,都应首先确定哪些过滤器适用:

DECLARE @p1_filter BIT;
DECLARE @p2_filter BIT;

SET @p1_filter = 0;
SET @p2_filter = 0;

IF EXISTS (SELECT TOP (1) * FROM Parameters1)
BEGIN
   SET @p1_filter = 1;
END;

IF EXISTS (SELECT TOP (1) * FROM Parameters2)
BEGIN
   SET @p2_filter = 1;
END;

2.A。动态SQL

如果您要使用动态SQL路由,则可以执行以下操作:

DECLARE @sql NVARCHAR(MAX);

SET @sql = 'SELECT * FROM Tran T ';

IF (@p1_filter = 1)
BEGIN
   SET @sql = @sql + 'INNER JOIN Parameters1 p1 ON T.code1 = p1.code1 ';
END;

IF (@p2_filter = 1)
BEGIN
   SET @sql = @sql + 'INNER JOIN Parameters2 p2 ON T.code2 = p2.code2 ';
END;

EXECUTE sp_executesql
   @statement = @sql
;

2.b.i。静态SQL:WHERE子句中的子SELECT

否则,你将继续使用这个丑陋的(可能表现不佳)静态SQL:

SELECT *
FROM Tran T
WHERE 
   (
         T.code1 IN (SELECT code1 FROM Parameters1)
      OR (@p1_filter = 0)
   )
   AND
   (
         T.code2 IN (SELECT code2 FROM Parameters2)
      OR (@p2_filter = 0)
   )
;

Erland还提出了我之前提到的that same page上的静态SQL方法。你可能会在那里找到更好的方法。

2.b.ii。静态SQL:LEFT OUTER JOIN

你也可以采用这种方法,你在这个答案的评论中提出了这个方法:

SELECT *
FROM 
                   Tran T
   LEFT OUTER JOIN Parameters1 p1
      ON T.code1 = p1.code1
   LEFT OUTER JOIN Parameters2 p2
      ON T.code2 = p2.code2
WHERE
       T.code1 = 
          CASE
             WHEN @p1_filter = 1
                THEN p1.code1
             ELSE T.code1
          END
   AND T.code2 =
          CASE
             WHEN @p2_filter = 1
                THEN p2.code2
             ELSE T.code2
          END
;

答案 1 :(得分:0)

尝试使用RIGHT JOIN

SELECT * FROM Tran T  
RIGHT JOIN Parameters1 p1 ON T.code1 = p1.code1  
JOIN Parameters2 p2 ON T.code2 = p2.code2  
WHERE p1.code1 is not null AND p2.code2 is not null  

答案 2 :(得分:0)

exists

怎么样?
select * from Tran t

where exists(select 1 from Parameters1 p1 where t.code1 = p.code1)

and  exists(select 1 from Parameters2 p2 where t.code2 = p.code2)

答案 3 :(得分:0)

我不确定我是否完全理解你想要实现的目标。如果BOTH有结果,你只想要结果吗?另外,我猜测你的连接中引用的p应该是参数1(p1)和参数2(p2)的表别名,而不仅仅是你问题中的(p)。

如果是这样,那么只需选择t。*和LEFT JOIN两个参数表,例如;

SELECT t.*  
FROM  
     Tran t 
     LEFT JOIN Parameters1 p1 ON T.code1 = p1.code1  
     LEFT JOIN Parameters2 p2 ON T.code2 = p2.code2  
WHERE p1.code1 is not null AND
      p2.code2 is not null