如何使用子查询循环构建数据?

时间:2019-08-25 09:23:46

标签: sql oracle oracle11g

我在一个表中列出了许多物料清单(BOM)。现在,每个BOM都有其自己的项目列表和称为半成品的子BOM。最近,我在这里得到了有关如何构建每个工作原理完美的BOM的帮助。该查询的缺点是使用参数一次只能支持一项。如果删除了商品代码的参数,则检索到的数据完全错误。

我需要开发查询,以便首先生成所有BOM的主列表,然后转到第一条记录并生成其完整路径(详细信息),然后为第二个主BOM循环并生成完整的路径,并将所有记录与先前的项目列表结合在一起,依此类推,直到到达BOM的最后一个主记录。

最后,我有正确正确的BOM表及其路径。

下面的查询我尝试使用游标,但它需要INTO

DECLARE
   CURSOR c1
   IS
        SELECT   BOM_ITEM_CODE BIC
          FROM   BOM_MASTER
         WHERE   BOM_FRZ_FLAG = 2
      GROUP BY   BOM_ITEM_CODE;
BEGIN
   FOR qry IN c1
   LOOP
          -- Start - The below query generates a complete path of any supplied Bill of Material Code
          SELECT   t.BI_ITEM_CODE,
                   BI_BOM_CODE,
                   BI_UOM_CODE,
                   BI_QTY,
                   BI_QTY_LS,
                   BI_QTY_BU,
                   SYS_CONNECT_BY_PATH (BI_BOM_CODE, '>') || '->' || BI_ITEM_CODE
                      AS PATH,
                   LEVEL,
                   CONNECT_BY_ISCYCLE LOOPING_ITEM
            FROM   BOM_ITEM_DETAIL t
      START WITH   BI_BOM_CODE = qry.BIC --This paramter is where the Master Bill of Material Code is supplied.
      CONNECT BY   NOCYCLE PRIOR BI_ITEM_CODE =
                              (SELECT   BOM_ITEM_CODE
                                 FROM   BOM_MASTER
                                WHERE   BOM_CODE = BI_BOM_CODE
                                        AND BOM_FRZ_FLAG = 2);
   -- End of Query which generates the complete path of any supplied Bill of Material Code
   END LOOP;
END;
/

我也尝试使用WITH,但是它没有提供正确的数据。它尝试列出所有记录,其中在所有级别使用主BOM表代码。

SELECT   *
    FROM   (WITH qry AS (  SELECT   BOM_ITEM_CODE BIC
                             FROM   BOM_MASTER
                            WHERE   BOM_FRZ_FLAG_NUM = 2
                         GROUP BY   BOM_ITEM_CODE
                         ORDER BY   BOM_ITEM_CODE)
                SELECT   t.BI_ITEM_CODE,
                         BI_BOM_CODE,
                         BI_UOM_CODE,
                         BI_QTY,
                         BI_QTY_LS,
                         BI_QTY_BU,
                            SYS_CONNECT_BY_PATH (BI_BOM_CODE, '>')
                         || '->'
                         || BI_ITEM_CODE
                            AS PATH,
                         LEVEL
                  FROM   BOM_ITEM_DETAIL t, qry
                 WHERE   BI_BOM_CODE = qry.BIC
            START WITH   BI_BOM_CODE = qry.BIC
            CONNECT BY   NOCYCLE PRIOR BI_ITEM_CODE =
                                    (SELECT   BOM_ITEM_CODE
                                       FROM   BOM_MASTER
                                      WHERE   BOM_CODE = BI_BOM_CODE
                                              AND BOM_FRZ_FLAG_NUM = 2))
ORDER BY PATH

我之前的问题没有得到很好的回答,因为我忘记提及我尝试过的示例查询。

我先前的问题和可接受的答案中的工作示例查询/数据:

How to get all levels data using single SQL query for bill of material

1 个答案:

答案 0 :(得分:0)

在这种情况下,以条件开头位于主表中,而子项位于子表中。

我已经演示了一个小代码来可视化并解决相同的问题。

CREATE TABLE M (ID NUMBER);
INSERT INTO M VALUES(1);
INSERT INTO M VALUES(10);
commit;
CREATE TABLE T1 (ID NUMBER, PARENT_ID NUMBER);
INSERT INTO T1 VALUES (1,NULL);
INSERT INTO T1 VALUES (3,1);
INSERT INTO T1 VALUES (2,1);
INSERT INTO T1 VALUES (4,2);
INSERT INTO T1 VALUES (5,2);
INSERT INTO T1 VALUES (10,NULL);
INSERT INTO T1 VALUES (12,10);
INSERT INTO T1 VALUES (7,10);
INSERT INTO T1 VALUES (11,10);
INSERT INTO T1 VALUES (6,1);
INSERT INTO T1 VALUES (13,1);
COMMIT;

查询以获取所需结果:

SELECT T1.ID, M.ID,
SYS_CONNECT_BY_PATH ( T1.id, '>') AS PATH, LEVEL
FROM
T1 LEFT JOIN M -- did left join on master table
ON (T1.ID = M.ID)
CONNECT BY PRIOR T1.ID =  T1.PARENT_ID
START WITH M.ID IS NOT NULL -- start with a condition (IMP)

输出:

enter image description here

干杯!