拉动不同数据的麻烦

时间:2015-03-20 12:56:07

标签: sql sql-server

好的,这很难解释,因为我在sql上很糟糕,但是这段代码并没有完全按照我的意愿去做。我将尝试尽可能地解释它应该做什么,希望有人能发现一个明显的错误。我对这个冗长的解释感到抱歉,但是这里有很多事情,我真的可以使用这个帮助。

此脚本的目的是搜索需要废弃的部件。换句话说,他们三年没有使用,仍然活跃。

当我们废弃部分时,“part.status”被设置为“O”。通常为空。此外,“OBSOLETE”一词通常写在“part.description”

“WORK_ORDER”包含每个预定的工单。这些由base,lot和sub ID定义。它还包含许多日期,例如工作单关闭的日期。

“REQUIREMENT”表包含每个作业所需的所有部件。许多工作可能需要多个部分,有些部分在工作的不同部分。处理此方法的方法是,对于给定的“REQUIREMENT.WORKORDER_BASE_ID”和“REQUIREMENT.WORKORDER_LOT_ID”,它们可能会列在十几个后续行中。每行指定不同的“REQUIREMENT.PART_ID”。 sub id分隔了需要该部分的作业的哪一段。我关心的所有部分都以'PCH'开头

当我运行此代码时,它返回14行,我碰巧知道它现在应该返回大约39行。我相信这个棘手的部分从第17行开始。我发现另一个表单上的代码希望它能帮助解决原始问题。如果没有这些代码,我会得到27K行,因为数据库正在从匹配工单的每个条件中提取符合要求的每个条件。其中许多部件用于多种作业。我也尝试在REQUIREMENT.PART_ID上使用DISTINCT,这似乎应该可以解决问题。唉它没有。

所以我知道尽管所有的信息,我可能仍然没有提供足够的信息。有没有人有什么建议?

SELECT
PART.ID [Engr Master]
,PART.STATUS [Master Status]
,WO.CLOSE_DATE  
,PT.ID  [Die]
,PT.STATUS  [Die Status]

FROM PART
CROSS APPLY(
    SELECT 
    WORK_ORDER.BASE_ID
    ,WORK_ORDER.LOT_ID
    ,WORK_ORDER.SUB_ID
    ,WORK_ORDER.PART_ID
    ,WORK_ORDER.CLOSE_DATE
    FROM WORK_ORDER
    WHERE 
        GETDATE() - (360*3) > WORK_ORDER.CLOSE_DATE
        AND PART.ID = WORK_ORDER.PART_ID
        AND PART.STATUS ='O'
    )WO
CROSS APPLY(
    SELECT
    REQUIREMENT.WORKORDER_BASE_ID
    ,REQUIREMENT.WORKORDER_LOT_ID
    ,REQUIREMENT.WORKORDER_SUB_ID
    ,REQUIREMENT.PART_ID
FROM REQUIREMENT
WHERE
    WO.BASE_ID = REQUIREMENT.WORKORDER_BASE_ID
    AND WO.LOT_ID = REQUIREMENT.WORKORDER_LOT_ID
    AND WO.SUB_ID = REQUIREMENT.WORKORDER_SUB_ID
    AND REQUIREMENT.PART_ID LIKE 'PCH%'

)REQ
CROSS APPLY(
SELECT
    PART.ID
    ,PART.STATUS
FROM PART
WHERE 
    REQ.PART_ID = PART.ID
    AND PART.STATUS IS NULL

)PT
ORDER BY PT.ID

1 个答案:

答案 0 :(得分:0)

如果没有任何样本数据,这很难理解,但无论如何我都试了一下。我删除了第二个JOIN到PART(有别名PART1),因为它似乎是不必要的。我还删除了正在寻找HAVING COUNT(PART_ID)= 1

部分的子查询

第一次JOIN到PART应该在REQUIREMENT.PART_ID = PART.PART_ID上完成,因为已经从WORK_ORDER到REQUIREMENT定义了关系,因此您可以在此时直接将PART连接到REQUIREMENT。

编辑03/23/2015 如果我理解正确,你只需要一个不同的PCH部分列表,以及它们各自的最后一个(读取:MAX)CLOSE_DATE。如果是这种情况,这就是我的建议。

我把查询分成了几个CTE。第一个CTE只是通过PART表并拉出一个DISTINCT PCH部件列表,按PART_ID和DESCRIPTION进行分组。

第二个CTE正在通过REQUIREMENT表,加入WORK_ORDER表,并且对于每个PART_ID(由PARTITION处理),按降序分配CLOSE_DATE一个ROW_NUMBER。这将确保每个ROW_NUMBER的值为" 1"将是每个PART_ID的最大CLOSE_DATE。

最后的SELECT语句只是在PART_ID上加入两个Cte,过滤LastCloseDate = 1(在第二个CTE中分配的ROW_NUMBER)。

如果我理解正确的要求,这应该会给你想要的结果。

此外,我删除了过滤器WHERE PART.DESCRIPTION NOT LIKE' OB%'因为我们已经通过PART过滤了.STATUS是空的,你在上面说过一个' O'在此字段中放置过时部件。此外,[DIE]和[ENGR MASTER]在之前拉出的27行中具有相同的值,因此我只使用了相同的字段并对它们进行了不同的标记。

; WITH Parts AS(
    SELECT prt.PART_ID AS [ENGR MASTER]
            , prt.DESCRIPTION
      FROM PART prt 
     WHERE prt.STATUS IS NULL
       AND prt.PART_ID LIKE 'PCH%'
     GROUP BY prt.ID, prt.DESCRIPTION
)
, LastCloseDate AS(
    SELECT req.PART_ID
            , wrd.CLOSE_DATE
            , ROW_NUMBER() OVER(PARTITION BY req.PART_ID ORDER BY wrd.CLOSE_DATE DESC) AS LastCloseDate
      FROM REQUIREMENT req
     INNER JOIN WORK_ORDER wrd
        ON wrd.BASE_ID = req.WORKORDER_BASE_ID
       AND wrd.LOT_ID = req.WORKORDER_LOT_ID
       AND wrd.SUB_ID = req.WORKORDER_SUB_ID
     WHERE wrd.CLOSE_DATE IS NOT NULL
       AND GETDATE() - (365 * 3) > wrd.CLOSE_DATE
)
SELECT prt.PART_ID AS [DIE]
        , prt.PART_ID AS [ENGR MASTER]
        , prt.DESCRIPTION
        , lst.CLOSE_DATE
  FROM Parts prt
 INNER JOIN LastCloseDate lst
    ON prt.PART_ID = lst.PART_ID
 WHERE LastCloseDate = 1