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

条件联接的最佳方式-SQL Server,sql,sql-server,Sql,Sql Server,我有两个表,表A总是有数据,表B可以是空的。当我知道表B为空时,我想将@Filter参数设置为0,并查看表A中的所有记录(然后忽略表B)。当我知道表B不是空的时,我想将@Filter参数设置为1,以仅显示两个表之间的公共行(使用列X和Y) 我从未找到明确的解决方案,我尝试了不同的方法,但没有一种是我喜欢的: exec@sqlString:潜在的sql注入/不太可读的代码(IMHO) 联合:我的查询太大,无法复制 或在WHERE条件下:在某些情况下速度太慢 DECLARE @Filter BI

我有两个表,表A总是有数据,表B可以是空的。当我知道表B为空时,我想将@Filter参数设置为0,并查看表A中的所有记录(然后忽略表B)。当我知道表B不是空的时,我想将@Filter参数设置为1,以仅显示两个表之间的公共行(使用列X和Y)

我从未找到明确的解决方案,我尝试了不同的方法,但没有一种是我喜欢的:

  • exec@sqlString:潜在的sql注入/不太可读的代码(IMHO)
  • 联合:我的查询太大,无法复制
  • 或在WHERE条件下:在某些情况下速度太慢

     DECLARE @Filter BIT = 0
    
     SELECT A.*
     FROM   A, B
     WHERE  @Filter = 0 OR (B.X = A.X AND B.Y = A.Y)
    

有人知道另一种方法吗?

从左连接到B开始,这样您就可以始终建立a-B关系

然后,在where子句中测试过滤器。
如果为0,则获取所有

如果为1,请确保B.X字段不为NULL(因此存在),并且只返回两个表中的记录

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 ))

您可以使用
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

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

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)

左键连接什么?您有一个所谓的“全包查询”。这些在搜索中非常常见。他们肯定会有挑战性。盖尔·肖(Gail Shaw)在这个话题上有一篇很棒的文章。这是来自Erland Sommarskog的另一个例子,这可能会导致一些相当困难的性能问题。我不会复制我的选择,sorry@SeanLange没错,但考虑到我们对这些表的性质了解很少,OP已经使用UNION、WHERE和动态SQL打折了。这只是另一种选择(虽然不是我喜欢的)。不幸的是,这会减慢我的查询速度