如何在3个表之间进行条件连接

时间:2018-02-27 13:43:40

标签: sql-server

我有一个带有表变量的存储过程作为输入:

CREATE TYPE [dbo].[IDArray] AS TABLE ([ID] INT NULL);

程序

CREATE PROCEDURE [dbo].[GetFiltered](   
    @IDs as IDArray READONLY
)

AS
SELECT * FROM A JOIN (
    B JOIN @IDs ON B.BID = @IDs.ID
) ON A.AID = B.AID;

@IDs参数用作B的过滤器。我的问题是,如果A为空,我希望过程从@IDs返回所有记录。我不能只进行外连接,因为这会使过滤过时。

示例数据:

Table A:
    AID | Name
    1   | X
    2   | Y
    3   | Z

Table B:
    BID | AID
    1   | 1
    2   | 1
    3   | 2
    4   | 2

使用过滤器调用过程(应返回ID为1的A的值):

DECLARE @IDs IDArray;
INSERT INTO @IDs([ID]) VALUES (1)
Execute GetFiltered @IDS

调用没有过滤器的过程(应该返回A的所有值):

DECLARE @IDs IDArray;
Execute GetFiltered @IDS

2 个答案:

答案 0 :(得分:0)

一种方法是使用existsnot exists
exists部分取代了joinB之间的@Ids
如果not exists不包含任何行,则@ids部分将返回所有行。

SELECT * 
FROM A 
JOIN B ON A.AID = B.AID
WHERE EXISTS 
(
    SELECT 1
    FROM @IDs ids
    WHERE ids.ID = B.BID
)
OR NOT EXISTS
(
    SELECT 1
    FROM @IDs
)    

答案 1 :(得分:0)

我想我现在想出了一个答案。它可以通过左外部来解决。然后我只需要在连接表上检查null,如果没有设置过滤器,则只允许它为null。

CREATE PROCEDURE [dbo].[GetFiltered](   
    @IDs as IDArray READONLY
)

AS

DECLARE @Filtered bit;

IF Exists(SELECT * FROM @IDS)
    SET @Filtered = 1;
ELSE
    SET @Filtered = 0;

SELECT * FROM A LEFT OUTER JOIN (
    B JOIN @IDs ON B.BID = @IDs.ID
) ON A.AID = B.AID
WHERE Not B.AID IS NULL OR @Filtered = 0;