最佳的条件连接方式 - SQL Server

3
我有两个表,表A总是有数据,表B可能为空。当我知道表B为空时,我想将@Filter参数设置为0,并查看表A中的所有记录(忽略表B)。当我知道表B不为空时,我想将@Filter参数设置为1,仅显示两个表之间共同的行(使用列X和Y)。
我从未找到过一个确定的解决方案,我尝试了不同的方法,但都不理想:
  • exec @sqlString: potential sql injection / not very readable code (IMHO)
  • UNION: My query is too large to duplicate
  • OR in WHERE condition: Too slow in some cases

     DECLARE @Filter BIT = 0
    
     SELECT A.*
     FROM   A, B
     WHERE  @Filter = 0 OR (B.X = A.X AND B.Y = A.Y)
    
有没有其他的方法?

1
LEFT JOIN 是什么? - jarlh
1
你有一个被称为“万能查询”的查询。这在搜索中非常常见。它们肯定是具有挑战性的。Gail Shaw在这个主题上有一篇很棒的文章,链接在这里:http://www.sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/ 这里还有另一篇来自Erland Sommarskog的文章:http://www.sommarskog.se/dyn-search-2005.html - Sean Lange
3个回答

4

首先左联接B表,以确保建立A-B的关系。

然后,在where子句中测试筛选条件。
如果为0,则获取所有记录。

或者

如果为1并且确保B表的X字段不为空(即存在),则返回两个表中仅符合条件的记录。

SELECT 
      A.* 
   FROM 
      A LEFT JOIN B 
           ON A.X = B.X AND A.Y = B.Y
   where
           @Filter = 0
      OR ( @Filter = 1 AND NOT ISNULL( B.X ))

1
不幸的是,这会减慢我的查询速度。 - Rick

1
你可以使用一个 IF 语句。
IF EXISTS (SELECT TOP 1 X FROM B) -- make sure something is there
  BEGIN
    -- if there is, do the join
    SELECT *
    FROM A
    INNER JOIN B ON B.X = A.X AND B.Y = A.Y
  END
ELSE
  BEGIN
    -- nothing in B, select everything from A
    SELECT *
    FROM A
  END

1
这可能会导致一些相当困难的性能问题。http://www.sqlinthewild.co.za/index.php/2009/09/15/multiple-execution-paths/ - Sean Lange
抱歉,我不会重复我的SELECT。 - Rick
@SeanLange 没错,但考虑到我们对这些表的性质知之甚少,而且 OP 已经排除了使用 UNION、WHERE 和动态 SQL。这只是另一种选择(尽管不是我首选的)。 - Becuzz

0

我相信你正在寻找类似这样的东西:

SELECT A.* 
FROM
   A  
WHERE 
   EXISTS(SELECT 1 from B WHERE A.X = B.X AND A.Y = B.Y)
   OR NOT EXISTS(SELECT 1 FROM B)

如果表B为空,则它将显示表A中的所有记录,如果表B不为空,则只显示表A中的共同记录

完整代码:

declare  @A table
(
    x int,
    y int 
)
declare  @B table
(
    x int,
    y int 
)

insert into @A
values(1,1),
(1,2)

--Uncomment code below to insert data in table B
--insert into @B
--values(1,1) --,
--(1,2)

SELECT A.* 
FROM
   @A A 
WHERE 
   EXISTS(SELECT 1 from @B B WHERE A.X = B.X AND A.Y = B.Y)
   OR NOT EXISTS(SELECT 1 FROM @B)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接