如何根据某些条件完成SQL连接?

如何根据某些条件完成SQL连接?,sql,sql-server,left-join,Sql,Sql Server,Left Join,我有两张桌子: CREATE TABLE Users( UserId UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, UserName NVARCHAR(200) NOT NULL, -- some other columns CurrentSubscriptionId UNIQUEIDENTIFIER NULL, ) CREATE TABLE Subscriptions( SubscriptionId UNIQUEIDEN

我有两张桌子:

CREATE TABLE Users(
    UserId UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
    UserName NVARCHAR(200) NOT NULL,
    -- some other columns
    CurrentSubscriptionId UNIQUEIDENTIFIER NULL,
)

CREATE TABLE Subscriptions(
    SubscriptionId UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
    UserId UNIQUEIDENTIFIER NOT NULL,
    -- some other columns
)
我有一个存储过程,用于检索“用户”列表及其“当前订阅”:

关键是,对于存储过程的某些调用,我只需要来自“订阅”的数据,而不需要来自其他调用的数据。因此,我将向存储过程中添加一个
@includeSubscriptionData
位参数(这是伪代码,我必须单独列出每个有条件包含的列):

希望能避免加入。所以我先试试这个:

DECLARE @includeSubscriptionData BIT;
SET @includeSubscriptionData=0;
SELECT List-Of-Columns-FromUsers,
    CASE WHEN @includeSubscriptionData THEN SubscriptionId ELSE NULL END
FROM Users LEFT OUTER JOIN Subscriptions ON
   Users.CurrentSubscriptionId=Subscriptions.SubscriptionId
WHERE SomeConditionOnUsers
该计划显示,仍然可以访问“订阅”


当位设置为零时,如何取消对第二个表的访问?

是否尝试将其放入联接条件中

DECLARE @includeSubscriptionData BIT;
SET @includeSubscriptionData=0;
SELECT List-Of-Columns-FromUsers,
    SubscriptionId
FROM Users LEFT OUTER JOIN Subscriptions ON
   Users.CurrentSubscriptionId=Subscriptions.SubscriptionId and @includeSubscriptionData = 1
WHERE SomeConditionOnUsers
OPTION(RECOMPILE)
方法1-控制流 方法2-修改联接
您可以使用IF/ELSE进行此操作

DECLARE @includeSubscriptionData BIT;
SET @includeSubscriptionData=0;

IF @includeSubscriptionData == 0
    BEGIN
        SELECT List-Of-Columns-FromUsers    
        FROM Users WHERE SomeConditionOnUsers
    END
ELSE
    BEGIN
        SELECT List-Of-Columns-FromUsers    
        FROM Users LEFT OUTER JOIN Subscriptions ON Users.CurrentSubscriptionId=Subscriptions.SubscriptionId
        WHERE SomeConditionOnUsers
    END

这样,我必须维护列列表两次。我尝试了第二种方法-仍然可以访问第二个表。@sharptooth你不能两全其美,我的朋友
;-)@sharptooth P.S.最终,我觉得第一种方法对你来说是最好的解决方案。如果您唯一的抱怨是您必须维护两列列表:这不是一个有效的理由。惰性代码=糟糕的代码
;-)@sharptooth可能值得一读:是的,我试过了-仍然可以访问第二个表。添加重新编译查询提示。编辑设置。是的,提示访问是有条件的。我不确定这个提示是否有负面影响。是的,第二个表将出现在查询计划中。但是,如果查看计划中的“实际行数”值,它将为零,即不执行IO。在我的测试中,添加该查询提示实际上会使第二个表不出现在查询计划中。YMMV SQL访问表
订阅
到底有什么问题?我唯一的想法是避免接触
订阅
表,通过动态SQL构建查询,但这本身就有很多问题。@NickyvV该查询运行时间更长,并且会增加服务器上的负载。可能会引起一些兴趣,因此我认为CurrentSubscriptionID至少需要是一个FK
DECLARE @includeSubscriptionData BIT;
SET @includeSubscriptionData=0;
SELECT List-Of-Columns-FromUsers,
    SubscriptionId
FROM Users LEFT OUTER JOIN Subscriptions ON
   Users.CurrentSubscriptionId=Subscriptions.SubscriptionId and @includeSubscriptionData = 1
WHERE SomeConditionOnUsers
OPTION(RECOMPILE)
IF @includeSubscriptionData = 1
  BEGIN
    SELECT list
         , of
         , columns
    FROM   Users
     INNER
      JOIN Subscriptions
        ON Users.CurrentSubscriptionId = Subscriptions.SubscriptionId
    WHERE  SomeConditionOnUsers
    ;
  END
ELSE
  BEGIN
    SELECT list
         , of
         , columns
    FROM   Users
    ;
  END
;
SELECT list
     , of
     , columns
FROM   Users
 LEFT
  JOIN Subscriptions
    ON Users.CurrentSubscriptionId = Subscriptions.SubscriptionId
   AND @includeSubscriptionData = 1
WHERE  SomeConditionOnUsers
DECLARE @includeSubscriptionData BIT;
SET @includeSubscriptionData=0;

IF @includeSubscriptionData == 0
    BEGIN
        SELECT List-Of-Columns-FromUsers    
        FROM Users WHERE SomeConditionOnUsers
    END
ELSE
    BEGIN
        SELECT List-Of-Columns-FromUsers    
        FROM Users LEFT OUTER JOIN Subscriptions ON Users.CurrentSubscriptionId=Subscriptions.SubscriptionId
        WHERE SomeConditionOnUsers
    END