添加基于IF语句的连接

时间:2011-01-17 14:40:32

标签: sql join if-statement

我想知道是否可以基于IF语句将连接添加到SQL语句中。我有一个包含三个变量的查询,我只想在实际填写第三个变量时包含连接。这是我的查询:

-- Returns all new woksteps for a given time period
-- Includes the ability to narrow down to a specific arrangment

DECLARE @start_added_date DATETIME
DECLARE @end_added_date DATETIME
DECLARE @arrang_part_key INT

SET @start_added_date = '1/4/2011'
SET @end_added_date = '1/5/2011'
SET @arrang_part_key = '1230631'

-- Compensate for CST in the database
SET @end_added_date = DATEADD(DAY, 1, @end_added_date)

SELECT DISTINCT
  PWS.Part_Work_Step_Key,
  O.Operation_Code,
  WS.Work_Step,
  PWS.Sort_Order,
  U.User_ID,
  PWS.Added_Date,
  PWS.Cycle_Time,
  ET.ECR_Type,
  E.ECR_No,
  PWS.Effective_Date,
  P.Part_No,
  P.Revision,
  P.Name
FROM Part_V_Part_Work_Step PWS
JOIN Part_V_Work_Step WS
  ON WS.Work_Step_Key = PWS.Work_Step_Key
JOIN Part_V_Operation O
  ON O.Operation_Key = PWS.Operation_Key
JOIN User U
  ON U.User_No = PWS.Added_By
JOIN Part_V_ECR E
  ON E.ECR_Key = PWS.Effective_ECR_Key
JOIN Part_V_ECR_Type ET
  ON E.ECR_Type_Key = ET.ECR_Type_Key
JOIN Part_V_Part_Work_Step_BOM PWSB
  ON PWSB.Part_Work_Step_Key = PWS.Part_Work_Step_Key
JOIN Part_V_BOM B
  ON B.BOM_Key = PWSB.BOM_Key
JOIN Part_V_Part P
  ON P.Part_Key = B.Part_Key

IF @arrang_part_key IS NOT NULL
BEGIN
JOIN 
(
    SELECT
      AGP.Part_Key
    FROM Part_V_Flat_BOM FB
    JOIN Part_V_Part AGP
      ON AGP.Part_Key = FB.Component_Part_Key
    JOIN Part_V_Part_Group PG
      ON AGP.Part_Group_Key = PG.Part_Group_Key
     AND PG.Part_Group = 'Engineering Group'
    WHERE FB.Part_Key = @arrang_part_key
) AG
  ON AG.Part_Key = P.Part_Key
END

WHERE PWS.Part_Key IS NULL
  AND PWS.Added_Date BETWEEN @start_added_date AND @end_added_date
  AND PWS.Active = 1

ORDER BY
  O.Operation_Code,
  PWS.Sort_Order

但是当我运行查询时,我得到了这个结果:

Error: Incorrect syntax near the keyword 'JOIN'
Error: Incorrect syntax near 'AG'

我开始认为这不是解决问题的正确方法。该查询试图一石二鸟,返回给定时间范围内的所有结果,然后允许过滤到特定排列(如果提供)。

3 个答案:

答案 0 :(得分:2)

这是无效的语法。

您有两种选择:

  • 编写动态SQL(可能是最糟糕的做法)
  • 写两个SELECT语句。一个用于IF
  • 的每个分支

IF @arrang_part_key IS NOT NULL
  BEGIN
    SELECT ...
      INNER JOIN ...
      ...
  END
ELSE
  BEGIN
    SELECT ...
      ...
  END

答案 1 :(得分:0)

你必须在两种情况下完全查询两个表,然后过滤掉,所以试试......

-- Returns all new woksteps for a given time period
-- Includes the ability to narrow down to a specific arrangment

DECLARE @start_added_date DATETIME
DECLARE @end_added_date DATETIME
DECLARE @arrang_part_key INT

SET @start_added_date = '1/4/2011'
SET @end_added_date = '1/5/2011'
SET @arrang_part_key = '1230631'

-- Compensate for CST in the database
SET @end_added_date = DATEADD(DAY, 1, @end_added_date)

SELECT DISTINCT
  PWS.Part_Work_Step_Key,
  O.Operation_Code,
  WS.Work_Step,
  PWS.Sort_Order,
  U.User_ID,
  PWS.Added_Date,
  PWS.Cycle_Time,
  ET.ECR_Type,
  E.ECR_No,
  PWS.Effective_Date,
  P.Part_No,
  P.Revision,
  P.Name
FROM Part_V_Part_Work_Step PWS
JOIN Part_V_Work_Step WS
  ON WS.Work_Step_Key = PWS.Work_Step_Key
JOIN Part_V_Operation O
  ON O.Operation_Key = PWS.Operation_Key
JOIN User U
  ON U.User_No = PWS.Added_By
JOIN Part_V_ECR E
  ON E.ECR_Key = PWS.Effective_ECR_Key
JOIN Part_V_ECR_Type ET
  ON E.ECR_Type_Key = ET.ECR_Type_Key
JOIN Part_V_Part_Work_Step_BOM PWSB
  ON PWSB.Part_Work_Step_Key = PWS.Part_Work_Step_Key
JOIN Part_V_BOM B
  ON B.BOM_Key = PWSB.BOM_Key
JOIN Part_V_Part P
  ON P.Part_Key = B.Part_Key
JOIN 
(
    SELECT
      AGP.Part_Key
    FROM Part_V_Flat_BOM FB
    JOIN Part_V_Part AGP
      ON AGP.Part_Key = FB.Component_Part_Key
    JOIN Part_V_Part_Group PG
      ON AGP.Part_Group_Key = PG.Part_Group_Key
     AND PG.Part_Group = 'Engineering Group'
    WHERE FB.Part_Key = 
) AG
  ON AG.Part_Key = P.Part_Key and (@arrang_part_key = P.Part_Key And Not @arrang_part_key is Null )
END

WHERE PWS.Part_Key IS NULL
  AND PWS.Added_Date BETWEEN @start_added_date AND @end_added_date
  AND PWS.Active = 1

ORDER BY
  O.Operation_Code,
  PWS.Sort_Order

答案 2 :(得分:0)

好的,所以通过IF块添加连接根本无法工作。但我找到了一种方法来进行查询以及尽可能多地使用可重复使用的代码。

查询有两个关键要素:

  1. 始终查询工作步骤
  2. 偶尔按照安排过滤
  3. 为了实现这一点,我使用了表变量和CTE(公用表表达式)的组合,然后将两个查询放入我的if..else块。

    新查询如下所示:

    -- Returns all new woksteps for a given time period
    -- Includes the ability to narrow down to a specific arrangment
    
    DECLARE @start_added_date DATETIME
    DECLARE @end_added_date DATETIME
    DECLARE @arrang_part_key INT
    
    SET @start_added_date = '1/4/2011'
    SET @end_added_date = '1/5/2011'
    SET @arrang_part_key = '1230631'
    --SET @arrang_part_key = NULL
    
    -- Compensate for CST in the database
    SET @end_added_date = DATEADD(DAY, 1, @end_added_date)
    
    DECLARE @Work_Step_Table TABLE
    (
      Customer_Number INT,
      Part_Work_Step_Key INT,
      Operation_Code VARCHAR(255),
      Work_Step VARCHAR(255),
      Sort_Order INT,
      User_Id VARCHAR(255),
      Added_Date DATETIME,
      Cycle_Time Float,
      ECR_Type VARCHAR(255),
      ECR_No INT,
      Effective_Date DATETIME,
      Part_Key INT,
      Part_No VARCHAR(255),
      Revision VARCHAR(255),
      Name VARCHAR(255)
    )
    
    INSERT INTO @Work_Step_Table
    SELECT DISTINCT
      P.Customer_Number,
      PWS.Part_Work_Step_Key,
      O.Operation_Code,
      WS.Work_Step,
      PWS.Sort_Order,
      U.User_ID,
      PWS.Added_Date,
      PWS.Cycle_Time,
      ET.ECR_Type,
      E.ECR_No,
      PWS.Effective_Date,
      P.Part_Key,
      P.Part_No,
      P.Revision,
      P.Name
    FROM Part_V_Part_Work_Step PWS
    JOIN Part_V_Work_Step WS
      ON WS.Work_Step_Key = PWS.Work_Step_Key
    JOIN Part_V_Operation O
      ON O.Operation_Key = PWS.Operation_Key
    JOIN User U
      ON U.User_No = PWS.Added_By
    JOIN Part_V_ECR E
      ON E.ECR_Key = PWS.Effective_ECR_Key
    JOIN Part_V_ECR_Type ET
      ON E.ECR_Type_Key = ET.ECR_Type_Key
    JOIN Part_V_Part_Work_Step_BOM PWSB
      ON PWSB.Part_Work_Step_Key = PWS.Part_Work_Step_Key
    JOIN Part_V_BOM B
      ON B.BOM_Key = PWSB.BOM_Key
    JOIN Part_V_Part P
      ON P.Part_Key = B.Part_Key
    
    WHERE PWS.Part_Key IS NULL
      AND PWS.Added_Date BETWEEN @start_added_date AND @end_added_date
      AND PWS.Active = 1
    
    
    IF (@arrang_part_key > 0)
    BEGIN 
    ;WITH Arrangement_Groups (PCN, Arrangement_Part_Key, Component_Part_Key) AS
    (
        SELECT
          AGP.Customer_Number,
          FB.Part_Key AS Arrangement_Part_Key,
          AGP.Part_Key AS Component_Part_Key      
        FROM Part_V_Flat_BOM FB
        JOIN Part_V_Part AGP
          ON AGP.Part_Key = FB.Component_Part_Key
        JOIN Part_V_Part_Group PG
          ON AGP.Part_Group_Key = PG.Part_Group_Key
         AND PG.Part_Group = 'Engineering Group'
        WHERE FB.Part_Key = @arrang_part_key
    )
    SELECT
      *
    FROM @Work_Step_Table WST
    JOIN Arrangement_Groups AG 
      ON AG.Component_Part_Key = WST.Part_Key  
    ORDER BY
      WST.Operation_Code,
      WST.Sort_Order
    END
    
    ELSE
     BEGIN
      SELECT
        *
      FROM @Work_Step_Table WST
      ORDER BY
        WST.Operation_Code,
        WST.Sort_Order
     END
    

    将始终创建表变量并使用日期范围的相关记录进行填充。 IF..Else块将检查是否有额外的布置键,并在需要时创建额外的CTE并相应地进行过滤。