了解基于条件的连接

时间:2014-10-09 07:58:12

标签: sql sql-server

好吧,我最终得到了一个1000行存储过程,我必须修改,在我当前的项目中。它目前正在使用过时的运算符,我必须用适当的连接替换它。它看起来像这样:

SELECT
     PRDE_Parts_Spec_ID
    ,PRDE_Service_Center_ID 
    ,ISNULL(SUM(ISNULL(PRDE_Qty_Required,0)),0) - ISNULL(SUM(ISNULL(PITM_Total_Qty_Received,0)),0)
FROM 
    TBL_Purchase_Request_Details 
    Inner Join 
    TBL_Purchase_Request_Master 
    ON PRMA_Purchase_Request_No = PRDE_Purchase_Request_No 
    Left Join 
    TBL_Parts_In_Txn_Master 
    ON ( PRDE_Parts_Spec_ID = PITM_Parts_Spec_ID AND 
         PRDE_Service_Center_ID = PITM_Service_Center_ID AND 
         PRDE_Required_Delivery_Date = PITM_Expected_Arrival_Date 
    )
WHERE
    PITM_Related_Request_Type_Id = 82 
    AND PRMA_PR_Status_ID IN (41,146,213,9097) --PO Raised,Received,Invoiced,Partially received statuses
    AND PRMA_Supplier_ID = 0
    AND PRMA_Order_Date < @dtEndDate    
    --and (
    --(PRMA_Purchase_Request_Type_ID != 145 AND PRMA_Purchase_Request_No *= PITM_Related_Request_No)
    --OR ( PRMA_Purchase_Request_Type_ID = 145 AND PRDE_MR_No *= PITM_Related_Request_No) 
    --)
    and not exists
    (SELECT POTM_Related_Txn_No 
    FROM TBL_Parts_Out_Txn_Master
    WHERE POTM_Related_Txn_No = PITM_Parts_In_Request_ID
    and POTM_Destination_Details = PITM_Source_Details
    and POTM_Destination_ID = PITM_Source_ID
    and POTM_Status_ID = 30) 

在where子句中,有一些注释行,根据条件完成左连接。

--and (
--(PRMA_Purchase_Request_Type_ID != 145 AND PRMA_Purchase_Request_No *= PITM_Related_Request_No)
--OR ( PRMA_Purchase_Request_Type_ID = 145 AND PRDE_MR_No *= PITM_Related_Request_No) 
--)

我已经更新了一些查询,您可以在FROM子句中看到。但是,我甚至无法理解如何在FROM子句中复制这种特殊条件。我肯定没有足够的经验来做到这一点。

编辑:

我想,这可能会造成一些混乱,因为列名不使用任何表别名。无论如何,列名的前4个字母表示它们所属的表名。 (不要怪我,这不是我的架构。这是一个20岁的代码,只需查看查询的证据)。

无论如何列的表名称:

TBL_Parts_In_Txn_Master -- PITM_Related_Request_No (All columns that start with PITM)
TBL_Purchase_Request_Details -- PRDE_MR_No (All columns that start with PRDE)
TBL_Purchase_Request_Master -- PRMA_Purchase_Request_No (All columns that start with PRMA)

编辑:

在修改原始查询之前添加原始查询。

SELECT
         PRDE_Parts_Spec_ID
        ,PRDE_Service_Center_ID 
        ,ISNULL(SUM(ISNULL(PRDE_Qty_Required,0)),0) - ISNULL(SUM(ISNULL(PITM_Total_Qty_Received,0)),0)
FROM 
TBL_Parts_In_Txn_Master
,TBL_Purchase_Request_Master
,TBL_Purchase_Request_Details

WHERE
    PRMA_Purchase_Request_No = PRDE_Purchase_Request_No 
    and PITM_Related_Request_Type_Id = 82 
    and PRDE_Parts_Spec_ID *= PITM_Parts_Spec_ID
    and PRDE_Service_Center_ID *= PITM_Service_Center_ID
    and PRDE_Required_Delivery_Date *= PITM_Expected_Arrival_Date
    and (
    (PRMA_Purchase_Request_Type_ID != 145 AND PRMA_Purchase_Request_No *= PITM_Related_Request_No)
    OR ( PRMA_Purchase_Request_Type_ID = 145 AND PRDE_MR_No *= PITM_Related_Request_No) 
    )
    --and (PITM_status_id=25 or PITM_status_id=77 or PITM_status_id=81) 
    and not exists
    (SELECT POTM_Related_Txn_No 
    FROM TBL_Parts_Out_Txn_Master
    WHERE POTM_Related_Txn_No = PITM_Parts_In_Request_ID
    and POTM_Destination_Details = PITM_Source_Details
    and POTM_Destination_ID = PITM_Source_ID
    and POTM_Status_ID = 30) 
    AND PRMA_PR_Status_ID IN (41,146,213,9097) --PO Raised,Received,Invoiced,Partially received statuses
    AND PRMA_Supplier_ID = 0
    AND PRMA_Order_Date < @dtEndDate

2 个答案:

答案 0 :(得分:2)

显示原始查询后修改:

在看到原始查询后,我不相信存在OUTER JOIN,在where子句中有过滤条件似乎否定了左连接,使其成为隐式内连接。特别是NOT EXISTS条件,它完全取决于(所谓的)左连接表中字段值的存在。

我也看不到存在2个OR的逻辑

所以,我会先尝试这个,只需使用INNER JOIN

SELECT
      PRDE.PRDE_Parts_Spec_ID
    , PRDE.PRDE_Service_Center_ID
    , ISNULL(SUM(ISNULL(PRDE.PRDE_Qty_Required, 0)), 0) - ISNULL(SUM(ISNULL(PITM.PITM_Total_Qty_Received, 0)), 0)
FROM TBL_Purchase_Request_Master PRMA
      INNER JOIN TBL_Purchase_Request_Details PRDE
                  ON PRMA.PRMA_Purchase_Request_No = PRDE.PRDE_Purchase_Request_No
      INNER JOIN TBL_Parts_In_Txn_Master PITM
                  ON PRDE.PRDE_Parts_Spec_ID = PITM.PITM_Parts_Spec_ID
                        AND PRDE.PRDE_Service_Center_ID = PITM.PITM_Service_Center_ID
                        AND PRDE.PRDE_Required_Delivery_Date = PITM.PITM_Expected_Arrival_Date
                        AND (
                              (PRMA.PRMA_Purchase_Request_Type_ID != 145
                                AND PRMA.PRMA_Purchase_Request_No = PITM.PITM_Related_Request_No)
                          OR 
                              (PRMA.PRMA_Purchase_Request_Type_ID = 145 
                                AND PRDE.PRDE_MR_No = PITM.PITM_Related_Request_No)
                            )
WHERE PRMA.PRMA_PR_Status_ID IN (41, 146, 213, 9097) --PO Raised,Received,Invoiced,Partially received statuses
      AND PRMA.PRMA_Supplier_ID = 0
      AND PRMA.PRMA_Order_Date < @dtEndDate
      AND NOT EXISTS (
            SELECT
                  POTM_Related_Txn_No
            FROM TBL_Parts_Out_Txn_Master
            WHERE POTM_Related_Txn_No = PITM.PITM_Parts_In_Request_ID
                  AND POTM_Destination_Details = PITM.PITM_Source_Details
                  AND POTM_Destination_ID = PITM.PITM_Source_ID
                  AND POTM_Status_ID = 30
      )
      AND PITM.PITM_Related_Request_Type_Id = 82
;

IF 有一个有效的OUTER JOIN然后我相信会是这样的:

SELECT
      PRDE.PRDE_Parts_Spec_ID
    , PRDE.PRDE_Service_Center_ID
    , ISNULL(SUM(ISNULL(PRDE.PRDE_Qty_Required, 0)), 0) - ISNULL(SUM(ISNULL(PITM.PITM_Total_Qty_Received, 0)), 0)
FROM TBL_Purchase_Request_Master PRMA
      INNER JOIN TBL_Purchase_Request_Details PRDE
                  ON PRMA.PRMA_Purchase_Request_No = PRDE.PRDE_Purchase_Request_No
      LEFT OUTER JOIN TBL_Parts_In_Txn_Master PITM
                  ON PRDE.PRDE_Parts_Spec_ID = PITM.PITM_Parts_Spec_ID
                        AND PRDE.PRDE_Service_Center_ID = PITM.PITM_Service_Center_ID
                        AND PRDE.PRDE_Required_Delivery_Date = PITM.PITM_Expected_Arrival_Date
                        AND (
                        (PRMA.PRMA_Purchase_Request_Type_ID != 145 AND PRMA.PRMA_Purchase_Request_No = PITM.PITM_Related_Request_No)
                        OR (PRMA.PRMA_Purchase_Request_Type_ID = 145 AND PRDE.PRDE_MR_No = PITM.PITM_Related_Request_No)
                        )
                        AND PITM.PITM_Related_Request_Type_Id = 82
 WHERE PRMA.PRMA_PR_Status_ID IN (41, 146, 213, 9097) --PO Raised,Received,Invoiced,Partially received statuses
      AND PRMA.PRMA_Supplier_ID = 0
      AND PRMA.PRMA_Order_Date < @dtEndDate
      AND NOT EXISTS (
            SELECT
                  POTM_Related_Txn_No
            FROM TBL_Parts_Out_Txn_Master
            WHERE POTM_Related_Txn_No = PITM.PITM_Parts_In_Request_ID
                  AND POTM_Destination_Details = PITM.PITM_Source_Details
                  AND POTM_Destination_ID = PITM.PITM_Source_ID
                  AND POTM_Status_ID = 30
      )
;

字段命名约定似乎包含对其所属表格的引用(例如 PRDE P urchase R equest的缩写 DE 尾巴)因此,虽然没有使用别名,但可以推断出每个字段所指的表格。

尽管如此,我还是引入了别名,如果你不想要它们,可能会被删除。

答案 1 :(得分:0)

根据您的更新信息,我们可以将注释掉的联接转换为:

and (
   (
    PRMA_Purchase_Request_Type_ID != 145 AND 
    TBL_Purchase_Request_Master.PRMA_Purchase_Request_No 
    *= 
    TBL_Parts_In_Txn_Master.PITM_Related_Request_No
   )
   OR 
   (
    PRMA_Purchase_Request_Type_ID = 145 AND 
    TBL_Purchase_Request_Details.PRDE_MR_No 
    *= 
    TBL_Parts_In_Txn_Master.PITM_Related_Request_No
   ) 
)

这意味着我们需要在

之间进行左外连接
  1. TBL_Purchase_Request_MasterTBL_Parts_In_Txn_Master

  2. TBL_Purchase_Request_DetailsTBL_Parts_In_Txn_Master

  3. 您已经在现有FROM子句中定义了第一个。你只需要为它添加条件。 AND它没有意义所以尝试OR:

    所以我认为你的FROM应该是这样的(但是如果没有看到数据模型就很难解决)

    FROM 
    TBL_Purchase_Request_Details 
    Inner Join 
    TBL_Purchase_Request_Master 
    ON PRMA_Purchase_Request_No = PRDE_Purchase_Request_No 
    Left Join 
    TBL_Parts_In_Txn_Master M
    ON (
         ( 
         M.PRDE_Parts_Spec_ID = PITM_Parts_Spec_ID AND 
         M.PRDE_Service_Center_ID = PITM_Service_Center_ID AND 
         M.PRDE_Required_Delivery_Date = PITM_Expected_Arrival_Date 
         )
         OR
         (
         TBL_Purchase_Request_Master.PRMA_Purchase_Request_Type_ID != 145 AND 
         TBL_Purchase_Request_Master.PRMA_Purchase_Request_No = M.PITM_Related_Request_No
         )
     OR
     (
         TBL_Purchase_Request_Master.PRMA_Purchase_Request_Type_ID = 145 AND 
         TBL_Purchase_Request_Details.PRDE_MR_No = M.PITM_Related_Request_No
         )
    

    我知道使用旧代码很烦人,但值得注意的是,如果它是一个复杂的转换,那么转换它的代码将变得复杂。您是希望将一堆不同的视图拼凑在一起(每个视图都可以进行单元测试),还是一个表示所有这些视图的HUMUNGOUS SQL语句?通常情况下,这些东西也是在严格的限制下建造的管理者对正确的事情并不感兴趣,只有编码员才会这样做,但我们不会拉扯。