2

次のテーブルがあります。

CREATE TABLE DBO.FACT_SERVICES (
    SVC_ID              INTEGER             NOT NULL,
    SVC_NAME            VARCHAR(50)         NOT NULL,
    SVC_DESC            VARCHAR(2000)       NULL,
    STATUS              VARCHAR(50)         NULL
);

CREATE TABLE DBO.FACT_TYPES (
    FACT_ID             INTEGER             NOT NULL,
    FACT_NAME           VARCHAR(100)        NOT NULL,
    FACT_DESC           VARCHAR(2000)       NULL,
    PARENT_FACT_ID      INTEGER             NULL,
);

CREATE TABLE DBO.FACT_TYPE_SVC (
    FACT_ID             INTEGER             NOT NULL,
    SVC_ID              INTEGER             NOT NULL,
    STATUS              VARCHAR(50)         NULL
);

XML 階層を取得するために、次のクエリを作成しました。

SELECT
  XMLElement("services", 
    XMLAgg(
      XMLElement("service",
        XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
        XMLElement("facts",
          (SELECT
          XMLAgg(
            XMLElement("fact", 
              XMLAttributes(FT.FACT_ID as "id", FT.FACT_NAME AS "name"),
              (SELECT
                XMLAgg(
                  XMLElement("fact",   
                    XMLAttributes(FT2.FACT_ID as "id", FT2.FACT_NAME as "name")
                  )
                )
                FROM
                  DBO.FACT_TYPES FT2 
                WHERE
                  FT2.PARENT_FACT_ID = FT.FACT_ID
              )                             
            )
          )
          FROM
            DBO.FACT_TYPES FT 
            INNER JOIN DBO.FACT_TYPE_SVC FTS ON FTS.FACT_ID = FT.FACT_ID
          WHERE
            FTS.SVC_ID = SVC.SVC_ID AND
            LOWER(FTS.STATUS) = 'active' AND
            PARENT_FACT_ID IS NULL
          )
        )
      )
    )
  )
FROM
  DBO.FACT_SERVICES SVC

次の XML を作成します。

<services>
    <service id="1" name="ABC Plan">
        <facts>
            <fact id="77" name="Basic Service">
                <fact id="71" name="Form XYZ Schedules"></fact>
                <fact id="101" name="Per Participant Fee"></fact>
                <fact id="103" name="Base Fee"></fact>
            </fact>
        </facts>
    </service>
</services>

ただし、FACT_TYPE の子を無制限に作成できるようにクエリを作成したいと考えています。私は Oracle で dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy()) 関数を使用していましたが、サービス部分で動作させることができないようです。DBO.FACT_TYPES テーブルから直接動作させることができます。

SELECT 
  XMLElement("facts",
  (select dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy('
        select level, 
                XMLElement("fact", 
                  XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
                )
        from
          dbo.fact_types ft
        start with parent_fact_id is null
        connect by prior fact_id = parent_fact_id
        order siblings by fact_name
  ')) from SYS.DUAL
  )
)AS XML_DATA 
FROM
  SYS.DUAL

どちらが返されますか:

<facts>
    <fact id="77" name="Basic Administrative Service">
        <fact id="103" name="Base Fee"/>
        <fact id="71" name="Form 5500+ Schedules"/>
        <fact id="101" name="Per Participant Fee"/>
    </fact>
</facts>

そこで、サービス ID を渡す関数を作成してみました。これは、サービスの階層に含まれる内部 XML を返します。

関数

create or replace
FUNCTION     dbo.FACT_GET_FACTS_XML(SERVICE_ID INT) 
RETURN XMLTYPE AS
INNER_SELECT DBMS_XMLGEN.ctxhandle;
MY_RESULT XMLTYPE;
BEGIN
INNER_SELECT := DBMS_XMLGEN.newcontextfromhierarchy(
        'select level, 
            XMLElement("fact", 
              XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
            )
          from
            dbo.fact_types ft
            inner join dbo.fact_type_svc fts on fts.fact_id = ft.fact_id
          where 
            fts.svc_id = ' || to_char(SERVICE_ID) || ' 
          start with ft.parent_fact_id is null
          connect by prior ft.fact_id = ft.parent_fact_id
          order siblings by ft.fact_name');

MY_RESULT := DBMS_XMLGEN.getxmltype(INNER_SELECT);
DBMS_XMLGEN.closeContext(INNER_SELECT);

RETURN MY_RESULT;

END;

この親クエリでは:

SELECT 
  XMLElement("services", 
    XMLAgg(
      XMLElement("service",
        XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
        (SELECT 
          XMLElement("facts",
          DBO.FACT_GET_FACTS_XML(SVC.SVC_ID))
        FROM
          SYS.DUAL)
      )
    )
  )
FROM
  DBO.FACT_SERVICES SVC

そして今、私はこの結果を得ています:

<services>
    <service id="1" name="ABC Plan">
        <facts>
            <fact id="77" name="Basic Service">
                <fact id="103" name="Base Fee"/>
                <fact id="71" name="Form XYZ Schedules"/>
                <fact id="101" name="Per Participant Fee"/>
                <fact id="103" name="Base Fee"/>
                <fact id="71" name="Form XYZ Schedules"/>
                <fact id="101" name="Per Participant Fee"/>
            </fact>
        </facts>
    </service>
    <service id="4" name="Health Retirement Account">
        <facts>
            <fact id="71" name="Form XYZ Schedules"/>
            <fact id="71" name="Form XYZ Schedules"/>
        </facts>
    </service>
</services>

私がXMLにしたいのは次のとおりです。

<services>
    <service id="1" name="ABC Plan">
        <facts>
            <fact id="77" name="Basic Service">
                <fact id="71" name="Form XYZ Schedules"></fact>
                <fact id="101" name="Per Participant Fee"></fact>
                <fact id="103" name="Base Fee"></fact>
            </fact>
        </facts>
    </service>
    <service id="4" name="Health Retirement Account">
      <facts></facts>
    </service>
</services>

ただし、子をファクト id="71" に追加して、その下に表示する機能があります。

編集 これが私が現在テーブルに持っているデータです

INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (71, 'Form 5500+ Schedules', '', 77);
INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (77, 'Basic Administrative Service', 'Master Group', );
INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (101, 'Per Participant Fee', '', 77);
INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (103, 'Base Fee', '', 77);

INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (77, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (77, 3, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (71, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (71, 3, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (71, 4, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (101, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (101, 3, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (101, 21, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (103, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (103, 3, 'ACTIVE');

INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (1, '401(k) Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (4, 'Health Retirement Account', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (5, 'Profit Sharing Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (2, 'Plan Money Purchase', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (3, '403(b) Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (21, 'ESOP Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (22, 'Health Savings Account', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (23, '457 Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (24, 'Simple Plan ', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (25, '503c Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (26, 'Cafeteria Plan', '', 'Active');
4

2 に答える 2

2

あなたが欲しいのはおそらくこれだけだと思いますか?

select XMLElement("services",
           XMLAgg(
             XMLElement("service",
               XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
              XMLElement("facts",
               (select dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy('
                   select level,
                          XMLElement("fact",
                            XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
                          )
                    from fact_types ft
                         inner join fact_type_svc fts
                                 on fts.fact_id = ft.fact_id
                   where fts.SVC_ID = ' || svc.svc_id || '
                   start with ft.parent_fact_id is null
                 connect by prior ft.fact_id = ft.parent_fact_id
                   order siblings by ft.fact_name
                      '))
                 from dual
                )
              )
            )
          )
        ) a
   from fact_services svc;

たとえば、いくつかのサンプルデータを使用します(余分な transform() 部分は無視してください..読みやすくするためにインデントを強制するために追加しました):

SQL> insert into FACT_TYPES
  2  select 77, 'Basic Service', '', null from dual union all
  3  select 101, 'Per Participant Fee', '', 77 from dual union all
  4  select 103, 'Base Fee', '', 77 from dual union all
  5  select 71, 'Form XYZ Schedules', '', null from dual union all
  6  select 72, 'Form XYZ Schedules 2', '', 71 from dual union all
  7  select 200, 'Test', '', 103 from dual  union all
  8  select 201, 'Another child', '', 200 from dual  union all
  9  select 202, 'FooBar', '', 200 from dual;

8 rows created.

SQL> insert into FACT_SERVICES
  2  select 1, 'ABC Plan', '', 'ACTIVE' from dual union all
  3  select 4, 'Health Retirement Account', '', 'ACTIVE' from dual;

2 rows created.

SQL> insert into FACT_TYPE_SVC
  2  select 77, 1, 'ACTIVE' from dual union all
  3  select 101, 1, 'ACTIVE' from dual union all
  4  select 103, 1, 'ACTIVE' from dual union all
  5  select 200, 1, 'ACTIVE' from dual union all
  6  select 201, 1, 'ACTIVE' from dual union all
  7  select 202, 1, 'ACTIVE' from dual union all
  8  select 71, 4, 'ACTIVE' from dual union all
  9  select 72, 4, 'ACTIVE' from dual;

8 rows created.

SQL> commit;

Commit complete.

SQL> select XMLElement("services",
  2             XMLAgg(
  3               XMLElement("service",
  4                 XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
  5                XMLElement("facts",
  6                 (select dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy('
  7                     select level,
  8                            XMLElement("fact",
  9                              XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
 10                            )
 11                      from fact_types ft
 12                           inner join fact_type_svc fts
 13                                   on fts.fact_id = ft.fact_id
 14                     where fts.SVC_ID = ' || svc.svc_id || '
 15                     start with ft.parent_fact_id is null
 16                   connect by prior ft.fact_id = ft.parent_fact_id
 17                     order siblings by ft.fact_name
 18                        '))
 19                   from dual
 20                  )
 21                )
 22              )
 23            )
 24          ).transform(xmltype('<xsl:stylesheet version="1.0"
 25   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 26   <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
 27   <xsl:template match="node()|@*">
 28    <xsl:copy>
 29     <xsl:apply-templates select="node()|@*"/>
 30    </xsl:copy>
 31   </xsl:template>
 32  </xsl:stylesheet>')) a
 33     from fact_services svc;

A
--------------------------------------------------------------------------------

<services>
 <service id="1" name="ABC Plan">
  <facts>
   <fact id="77" name="Basic Service">
    <fact id="103" name="Base Fee">
     <fact id="200" name="Test">
      <fact id="201" name="Another child">
      </fact>
      <fact id="202" name="FooBar">
      </fact>
     </fact>
    </fact>
    <fact id="101" name="Per Participant Fee">
    </fact>
   </fact>
  </facts>
 </service>
 <service id="4" name="Health Retirement Account">
  <facts>
   <fact id="71" name="Form XYZ Schedules">
    <fact id="72" name="Form XYZ Schedules 2">
    </fact>
   </fact>
  </facts>
 </service>
</services>
于 2013-01-14T21:23:09.083 に答える
1

あなたが提供したクエリで:

select 
    XMLElement("services",
        XMLAgg(
            XMLElement("service",
                XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
                XMLElement("facts",
                    (select dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy('
                        select level,
                            XMLElement("fact",
                                XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
                            )
                        from 
                            dbo.fact_types ft
                            inner join dbo.fact_type_svc fts on fts.fact_id = ft.fact_id
                        where 
                            fts.SVC_ID = ' || svc.svc_id || '
                        start with ft.parent_fact_id is null
                        connect by prior ft.fact_id = ft.parent_fact_id
                        order siblings by ft.fact_name
                    ')) from sys.dual
                    )
                )
            )
        )
    ) a
from 
    dbo.fact_services svc;

次の結果が得られます。

<services>
    <service id="1" name="401(k) Plan">
        <facts>
            <fact id="77" name="Basic Administrative Service">
                <fact id="103" name="Base Fee" />
                <fact id="71" name="Form 5500+ Schedules" />
                <fact id="101" name="Per Participant Fee" />
                <fact id="103" name="Base Fee" />
                <fact id="71" name="Form 5500+ Schedules" />
                <fact id="101" name="Per Participant Fee" />
            </fact>
        </facts>
    </service>
    <service id="4" name="Health Retirement Account">
        <facts>
            <fact id="71" name="Form 5500+ Schedules" />
            <fact id="71" name="Form 5500+ Schedules" />
        </facts>
    </service>
    <service id="5" name="Profit Sharing Plan ">
        <facts />
    </service>
    <service id="2" name="Plan Money Purchase">
        <facts />
    </service>
    <service id="3" name="403(b) Plan">
        <facts>
            <fact id="103" name="Base Fee" />
            <fact id="71" name="Form 5500+ Schedules" />
            <fact id="101" name="Per Participant Fee" />
            <fact id="77" name="Basic Administrative Service">
                <fact id="103" name="Base Fee" />
                <fact id="71" name="Form 5500+ Schedules" />
                <fact id="101" name="Per Participant Fee" />
            </fact>
        </facts>
    </service>
    <service id="21" name="ESOP Plan ">
        <facts>
            <fact id="101" name="Per Participant Fee" />
            <fact id="101" name="Per Participant Fee" />
        </facts>
    </service>
    <service id="22" name="Health Savings Account">
        <facts />
    </service>
    <service id="23" name="457 Plan ">
        <facts />
    </service>
    <service id="24" name="Simple Plan ">
        <facts />
    </service>
    <service id="25" name="503c Plan">
        <facts />
    </service>
    <service id="26" name="Cafeteria Plan ">
        <facts />
    </service>
</services>

しかし、 をsvc.svc_idからに移動するwhereinner join:

select 
    XMLElement("services",
        XMLAgg(
            XMLElement("service",
                XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
                XMLElement("facts",
                    (select dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy('
                        select level,
                            XMLElement("fact",
                                XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
                            )
                        from 
                            dbo.fact_types ft
                            inner join dbo.fact_type_svc fts on fts.fact_id = ft.fact_id AND fts.SVC_ID = ' || svc.svc_id || '
                        start with ft.parent_fact_id is null
                        connect by prior ft.fact_id = ft.parent_fact_id
                        order siblings by ft.fact_name
                    ')) from sys.dual
                    )
                )
            )
        )
    ) a
from 
    dbo.fact_services svc;

正しい XML 構造を取得します。

<services>
    <service id="1" name="401(k) Plan">
        <facts>
            <fact id="77" name="Basic Administrative Service">
                <fact id="103" name="Base Fee" />
                <fact id="71" name="Form 5500+ Schedules" />
                <fact id="101" name="Per Participant Fee" />
            </fact>
        </facts>
    </service>
    <service id="4" name="Health Retirement Account">
        <facts />
    </service>
    <service id="5" name="Profit Sharing Plan ">
        <facts />
    </service>
    <service id="2" name="Plan Money Purchase">
        <facts />
    </service>
    <service id="3" name="403(b) Plan">
        <facts>
            <fact id="77" name="Basic Administrative Service">
                <fact id="103" name="Base Fee" />
                <fact id="71" name="Form 5500+ Schedules" />
                <fact id="101" name="Per Participant Fee" />
            </fact>
        </facts>
    </service>
    <service id="21" name="ESOP Plan ">
        <facts />
    </service>
    <service id="22" name="Health Savings Account">
        <facts />
    </service>
    <service id="23" name="457 Plan ">
        <facts />
    </service>
    <service id="24" name="Simple Plan ">
        <facts />
    </service>
    <service id="25" name="503c Plan">
        <facts />
    </service>
    <service id="26" name="Cafeteria Plan ">
        <facts />
    </service>
</services>

最初の階層が処理された後、Oracle が where 条件を無視しているようです。ご協力ありがとうございました。

于 2013-01-15T15:02:04.410 に答える