oracle实现:取LOTNO max_measure_time之前的五个不同wwi.LOT_ID作为bsl_lot_id,应该如何修改这段代码 SELECT measuretime.LOTNO--B004957 ,measuretime.PRODUCT_ID--0668A ,measuretime.PRODUCT_NO --123 ,measuretime.TRIM_STAGE ,measuretime.T_WAFER_ID--B004957-03 ,measuretime.LOT_ID--1708380 ,measuretime.WAFER_ID--6519598 6521374 ,measuretime.WAFER_NO--03 04 ,measuretime.TEST_PROGRAM--0668A_WATY ,measuretime.WAT_PARAMETER_ID --123 ,measuretime.PARAMETER_NAME --VTSAT_855PG_1_D020 ,measuretime.limit_file ,measuretime.max_MEASURE_TIME ,wwi.LOT_ID AS bsl_LOT_ID --1708380 ,wwi.WAFER_ID AS bsl_WAFER_ID--6519598 6521374 ,wwi.WAFER_NO AS bsl_WAFER_NO--03 04 ,wwi.MEASURE_TIME AS bsl_MEASURE_TIME ,ROW_NUMBER() OVER (PARTITION BY measuretime.LOTNO ORDER BY wwi.MEASURE_TIME desc) AS rn FROM ( SELECT wat.LOTNO --B004957 ,wat.PRODUCT_ID --0668A ,p.PRODUCT_ID AS PRODUCT_NO --123 ,wat.TRIM_STAGE --WF_START ,wat.T_WAFER_ID --B004957-03 ,wat.LOT_ID --1708380 ,wat.WAFER_ID --6519598 6521374 ,wat.WAFER_NO --03 04 ,wat.TEST_PROGRAM --0668A_WATY ,PARA.WAT_PARAMETER_ID --123 ,PARA.PARAMETER_NAME --VTSAT_855PG_1_D020 ,PARA.limit_file ,MAX(wat.MEASURE_TIME) AS max_MEASURE_TIME --2025-03-07 FROM wat LEFT JOIN para on wat.TRIM_STAGE = para.STAGE_true AND wat.TEST_PROGRAM = para.TEST_PROGRAM AND wat.PRODUCT_ID = para.PRODUCT_ID LEFT JOIN PRODUCT p ON para.PRODUCT_ID = p.NAME --0668A GROUP BY wat.LOTNO --B004957 ,wat.PRODUCT_ID --0668A ,p.PRODUCT_ID --123 ,wat.TRIM_STAGE --WF_START ,wat.T_WAFER_ID --B004957-03 ,wat.LOT_ID --1708380 ,wat.WAFER_ID --6519598 6521374 ,wat.WAFER_NO --03 04 ,wat.TEST_PROGRAM --0668A_WATY ,PARA.WAT_PARAMETER_ID --123 ,PARA.PARAMETER_NAME --VTSAT_855PG_1_D020 ,PARA.limit_file HAVING PARA.PARAMETER_NAME='SRAM0015' ) measuretime LEFT JOIN WAT_WAFER_INFO wwi -- --------确认关联条件 参数 ON measuretime.max_MEASURE_TIME > wwi.MEASURE_TIME AND measuretime.TEST_PROGRAM = WWI.TEST_PROGRAM WHERE wwi.TEST_PROGRAM NOT LIKE '%M1%' AND wwi.TEST_PROGRAM NOT LIKE '%M4%' ORDER BY wwi.MEASURE_TIME desc
时间: 2025-06-21 08:25:55 浏览: 17
<think>嗯,用户的问题是关于如何在Oracle中修改SQL代码,实现获取某个LOTNO的max_measure_time之前的五个不同wwi.LOT_ID作为bsl_lot_id。首先我需要理解现有的SQL结构,然后找出需要调整的地方。
看一下原来的查询,主查询是从一个子查询measuretime左连接WAT_WAFER_INFO(wwi),并且用ROW_NUMBER()按LOTNO分区,按MEASURE_TIME降序排列生成rn。当前的关联条件是measuretime.max_MEASURE_TIME > wwi.MEASURE_TIME,并且TEST_PROGRAM相等。然后过滤掉TEST_PROGRAM包含M1或M4的记录,最后按MEASURE_TIME排序。
用户的需求是取每个LOTNO的max_measure_time之前的五个不同wwi.LOT_ID。原来的代码可能没有正确去重或者限制数量。可能需要用窗口函数或者其他方法来获取前五个不同的LOT_ID。
首先,需要确定如何获取不同LOT_ID。可能需要在PARTITION BY子句中包括LOTNO,然后按MEASURE_TIME降序排列,但还要去重。或者,可以先对wwi表进行分组,每个LOT_ID只取最大的MEASURE_TIME,然后再取前五。
另一个考虑点是当前的行号(ROW_NUMBER())可能没有考虑LOT_ID的去重,导致相同的LOT_ID被多次计数。可能需要使用DENSE_RANK或者ROW_NUMBER配合DISTINCT。
可能的修改步骤:
1. 在wwi的关联中,确保每个LOT_ID只取一次,可能需要子查询先按LOT_ID分组,取最大MEASURE_TIME。
2. 修改窗口函数,按LOTNO分区,并按MEASURE_TIME降序排列,然后使用ROW_NUMBER或DENSE_RANK来标记前五条。
3. 在WHERE子句中过滤rn <=5,并且确保LOT_ID不重复。
或者,在关联时,使用分析函数来为每个measuretime.LOTNO找到最近的五个不同wwi.LOT_ID。可能需要用DISTINCT在窗口函数中,但Oracle不支持DISTINCT在窗口函数里,所以需要先处理。
可能的解决方法是先为每个measuretime.LOTNO获取所有符合条件的wwi.LOT_ID,然后按MEASURE_TIME排序,去重后取前五。这可能需要使用子查询或WITH子句。
比如,在LEFT JOIN之前,先为每个measuretime生成一个排名,基于wwi.MEASURE_TIME,并且每个LOT_ID只计一次。可能需要用ROW_NUMBER() OVER (PARTITION BY measuretime.LOTNO, wwi.LOT_ID ORDER BY wwi.MEASURE_TIME DESC)来去重,然后取每个LOTNO的前五不同的LOT_ID。
或者,在JOIN的时候,使用子查询来预先处理wwi表,为每个LOT_ID保留最大MEASURE_TIME,然后关联到measuretime,并按时间排序取前五。
另外,现有的WHERE子句排除了TEST_PROGRAM包含M1和M4的情况,这可能影响结果集,需要确认是否必要。
总结修改步骤可能包括:
- 在wwi的JOIN条件中,确保每个LOT_ID只出现一次,按最大MEASURE_TIME。
- 使用分析函数为每个measuretime.LOTNO分配排名,基于wwi.MEASURE_TIME降序。
- 过滤排名前五的记录,并确保LOT_ID不同。
可能需要调整窗口函数的PARTITION BY和ORDER BY,以及处理去重的问题。例如,在子查询中先选出每个LOT_ID的最大MEASURE_TIME,然后在主查询中关联并排名,最后取前五。
或者,使用DENSE_RANK()而不是ROW_NUMBER(),因为DENSE_RANK会处理相同的值,但需要配合DISTINCT。可能需要在内层查询中先DISTINCT LOT_ID和MEASURE_TIME,然后再进行排名。
最终的修改可能涉及在wwi的JOIN部分使用子查询,预先处理数据,确保每个LOT_ID只出现一次,并且按MEASURE_TIME排序,然后应用ROW_NUMBER()来限制前五。</think>根据需求,需要获取每个`LOTNO`的`max_measure_time`之前的 **五个不同** `wwi.LOT_ID`。以下是分步修改方案:
---
### **步骤 1:明确需求与现有逻辑**
- **目标**:对每个`LOTNO`,找到其`max_measure_time`之前的所有`wwi.LOT_ID`,并取其中 **最新的五个不同值**。
- **问题分析**:
现有代码使用`ROW_NUMBER()`仅按时间排序,未去重,可能导致重复`LOT_ID`占用序号。
---
### **步骤 2:修改窗口函数**
需使用 **去重后按时间排序** 的窗口函数,并限制取前五条。
**修改点**:
```sql
-- 原代码中的ROW_NUMBER():
ROW_NUMBER() OVER (PARTITION BY measuretime.LOTNO ORDER BY wwi.MEASURE_TIME desc) AS rn
-- 改为DENSE_RANK() + 去重逻辑:
DENSE_RANK() OVER (
PARTITION BY measuretime.LOTNO
ORDER BY wwi.MEASURE_TIME DESC
) AS dr
```
---
### **步骤 3:添加去重逻辑**
在关联时,先对`wwi.LOT_ID`去重,确保每个`LOT_ID`仅保留最新的一条记录。
**修改点**:
```sql
LEFT JOIN (
SELECT
LOT_ID,
TEST_PROGRAM,
MAX(MEASURE_TIME) AS MEASURE_TIME -- 取每个LOT_ID的最新时间
FROM WAT_WAFER_INFO
GROUP BY LOT_ID, TEST_PROGRAM
) dedup_wwi -- 去重后的子查询
ON measuretime.TEST_PROGRAM = dedup_wwi.TEST_PROGRAM
AND measuretime.max_MEASURE_TIME > dedup_wwi.MEASURE_TIME
```
---
### **步骤 4:最终完整代码**
```sql
SELECT
measuretime.LOTNO,
measuretime.PRODUCT_ID,
measuretime.PRODUCT_NO,
measuretime.TRIM_STAGE,
measuretime.T_WAFER_ID,
measuretime.LOT_ID,
measuretime.WAFER_ID,
measuretime.WAFER_NO,
measuretime.TEST_PROGRAM,
measuretime.WAT_PARAMETER_ID,
measuretime.PARAMETER_NAME,
measuretime.limit_file,
measuretime.max_MEASURE_TIME,
dedup_wwi.LOT_ID AS bsl_LOT_ID,
DENSE_RANK() OVER (
PARTITION BY measuretime.LOTNO
ORDER BY dedup_wwi.MEASURE_TIME DESC
) AS dr
FROM (
SELECT
wat.LOTNO,
wat.PRODUCT_ID,
p.PRODUCT_ID AS PRODUCT_NO,
wat.TRIM_STAGE,
wat.T_WAFER_ID,
wat.LOT_ID,
wat.WAFER_ID,
wat.WAFER_NO,
wat.TEST_PROGRAM,
PARA.WAT_PARAMETER_ID,
PARA.PARAMETER_NAME,
PARA.limit_file,
MAX(wat.MEASURE_TIME) AS max_MEASURE_TIME
FROM wat
LEFT JOIN para
ON wat.TRIM_STAGE = para.STAGE_true
AND wat.TEST_PROGRAM = para.TEST_PROGRAM
AND wat.PRODUCT_ID = para.PRODUCT_ID
LEFT JOIN PRODUCT p
ON para.PRODUCT_ID = p.NAME
GROUP BY
wat.LOTNO,
wat.PRODUCT_ID,
p.PRODUCT_ID,
wat.TRIM_STAGE,
wat.T_WAFER_ID,
wat.LOT_ID,
wat.WAFER_ID,
wat.WAFER_NO,
wat.TEST_PROGRAM,
PARA.WAT_PARAMETER_ID,
PARA.PARAMETER_NAME,
PARA.limit_file
HAVING PARA.PARAMETER_NAME = 'SRAM0015'
) measuretime
LEFT JOIN (
SELECT
LOT_ID,
TEST_PROGRAM,
MAX(MEASURE_TIME) AS MEASURE_TIME
FROM WAT_WAFER_INFO
WHERE TEST_PROGRAM NOT LIKE '%M1%'
AND TEST_PROGRAM NOT LIKE '%M4%'
GROUP BY LOT_ID, TEST_PROGRAM
) dedup_wwi
ON measuretime.TEST_PROGRAM = dedup_wwi.TEST_PROGRAM
AND measuretime.max_MEASURE_TIME > dedup_wwi.MEASURE_TIME
WHERE dr <= 5 -- 取前五个不同的LOT_ID
ORDER BY dedup_wwi.MEASURE_TIME DESC;
```
---
### **关键修改说明**
1. **去重子查询**:
通过`GROUP BY LOT_ID, TEST_PROGRAM`确保每个`LOT_ID`仅保留最新的一条记录。
2. **窗口函数改用`DENSE_RANK`**:
当存在相同`MEASURE_TIME`时,`DENSE_RANK`会并列排名,避免因时间相同而漏掉数据。
3. **过滤条件`dr <= 5`**:
最终仅保留排名前五的不同`LOT_ID`。
---
### **验证建议**
1. 检查`dedup_wwi`子查询是否已正确去重。
2. 确认`DENSE_RANK()`的排序结果是否符合预期。
3. 测试极端情况(如不足五条记录或完全重复数据)。
阅读全文
相关推荐



















