好的,这很难解释,因为我在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
答案 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