oracle 尝试解析ORA-01427:单行子查询返回多行

ddrv8njm  于 2023-11-17  发布在  Oracle
关注(0)|答案(2)|浏览(258)

我有一系列记录,它们具有多个备用bin定义(BIN_BIN)。
举例来说:
x1c 0d1x的数据
我有一个查询,当只有一个备用位置时,它可以工作。当有多个备用位置时,它会失败。我已经尝试了几种方法,例如使用IN和替换EXISTS,使用RANK和PARTITION,但都没有成功。我必须合并数千行,这些行具有不同数量的匹配PART_NO,MFG和LOCATION记录,这些记录具有不同的BIN_BLOG值。

update PART_LOCATION a
    set alt_bin_loc_1 = 
    (
     select bin_loc
     from PART_LOCATION b where a.part_no = b.part_no and a.mfg = b.mfg and a.location = b.location and a.bin_loc <> b.bin_loc
     and a.temp_id < b.temp_id
    )
    where exists
    (
     select bin_loc
     from PART_LOCATION b where a.part_no = b.part_no and a.mfg = b.mfg and a.location = b.location and a.bin_loc <> b.bin_loc
     and a.temp_id < b.temp_id
    );

字符串
要将ALT_BIN_XXX位置与主记录中具有最低TEMP_ID的PART_ID/PART_NO、MFG、LOCATION上的匹配记录合并,然后删除下一个BIN_BIN不匹配的记录,需要完成的操作。如以下步骤所示。
第一次迭代结果:

第二次迭代结果:

第三次迭代结果:

6l7fqoea

6l7fqoea1#

您可以在一个MERGE语句中完成所有操作,方法是使用解析函数查找最低温度行,然后对其他行进行排序并旋转以查找alt. bin位置:

MERGE INTO table_name dst
USING (
  SELECT part_id,
         part_no,
         mfg,
         location,
         MAX(CASE WHEN grp = 1 AND bin_rn = 1 THEN bin_loc END) AS bin_loc,
         MAX(CASE WHEN grp = 2 AND bin_rn = 1 THEN bin_loc END) AS alt_bin_loc1,
         MAX(CASE WHEN grp = 2 AND bin_rn = 2 THEN bin_loc END) AS alt_bin_loc2,
         MAX(CASE WHEN grp = 2 AND bin_rn = 3 THEN bin_loc END) AS alt_bin_loc3,
         MIN(temp_id) AS temp_id
  FROM   (
    SELECT t.*,
           ROW_NUMBER() OVER (
             PARTITION BY part_id, part_no, mfg, location, grp
             ORDER BY bin_loc
           ) AS bin_rn
    FROM   (
      SELECT part_id,
             part_no,
             mfg,
             location,
             bin_loc,
             temp_id,
             LEAST(
               ROW_NUMBER() OVER (
                 PARTITION BY part_id, part_no, mfg, location
                 ORDER BY temp_id
               ),
               2
             ) AS grp
      FROM   table_name t
    ) t
  )
  GROUP BY
         part_id,
         part_no,
         mfg,
         location
) src
ON (    src.part_id  = dst.part_id
    AND src.part_no  = dst.part_no
    AND src.mfg      = dst.mfg
    AND src.location = dst.location)
WHEN MATCHED THEN
  UPDATE
  SET alt_bin_loc1 = src.alt_bin_loc1,
      alt_bin_loc2 = src.alt_bin_loc2,
      alt_bin_loc3 = src.alt_bin_loc3
  DELETE WHERE dst.bin_loc != src.bin_loc;

字符串
其中,对于样本数据:

CREATE TABLE table_name (
  part_id      NUMBER,
  part_no      VARCHAR2(10),
  mfg          VARCHAR2(10),
  location     NUMBER,
  bin_loc      VARCHAR2(10),
  alt_bin_loc1 VARCHAR2(10),
  alt_bin_loc2 VARCHAR2(10),
  alt_bin_loc3 VARCHAR2(10),
  temp_id      NUMBER
);

INSERT INTO table_name (part_id, part_no, mfg, location, bin_loc, temp_id)
SELECT 950, 'A1234', 'MFG1', 75309, 'A07',    123 FROM DUAL UNION ALL
SELECT 950, 'A1234', 'MFG1', 75309, 'LFRONT', 129 FROM DUAL UNION ALL
SELECT 950, 'A1234', 'MFG1', 75309, 'LTOP',   128 FROM DUAL UNION ALL
SELECT 950, 'A1234', 'MFG1', 75309, 'RFRONT', 127 FROM DUAL;


然后,在MERGE之后,该表包含:
| 部件ID|零件编号|Mfg|位置|联系我们|ALT_BIN_LOC 1| ALT_BIN_LOC 2| ALT_BIN_LOC 3|温度ID|
| --|--|--|--|--|--|--|--|--|
| 950 |A1234| Mfg1| 75309 |A07| LFRONT| LTOP| RFRONT| 123 |

  • 注意:如果你只是想 * 显示 * 透视数据(而不是修改表),那么只需在USING子句中使用SELECT。*

fiddle

yvgpqqbh

yvgpqqbh2#

不建议将值放在多个列中,如果出现的次数更多,则最终会有许多列。您可以将它们分组到单个列中,并为每个出现的值使用分隔符。您可以使用LISTAGG如下所示,

select part_id, part_no, mfg, location, 
LISTAGG(bin_loc, '; ') WITHIN GROUP (ORDER BY part_id, part_no, mfg, location) as bin_loc
from part_location;

字符串

相关问题