У меня есть иерархическая таблица узлов с 2 таблицами «Атрибуты» и «Значения», связанными между собой таблицей связей. Теперь я пытаюсь сделать запрос, чтобы вернуть определенное дерево для каждого узла с атрибутами и значениями его дочерних узлов независимо от уровня.
Поскольку я не нашел способа сделать это в одном запросе, я разделил его на 2, где я получаю детей отдельно и рекурсивно, используя хранимые процедуры. Приведенный ниже запрос собирает дочерние узлы и всю их информацию для определенного родителя.
Однако я столкнулся со странным поведением:
Сначала я получаю узлы и использую подзапрос для получения атрибутов. Отдельно эти запросы работают нормально, однако после их объединения они игнорируют фильтрацию и просто распечатывают все атрибуты, как только я пытаюсь устранить дубликаты с помощью DISTINCT.
select xmlelement("tns:nodes",
xmlattributes('http://somenamespace.com/' as "xmlns:tns"),
xmlagg(xmlelement("tns:node",
xmlelement("tns:code", n.code),
(select xmlelement("tns:attributes",
xmlagg(xmlelement("tns:attribute",
xmlelement("tns:name", t.name)
))
)
from (select DISTINCT att_a.name
from attributes2 att_a
inner join attrib_value_node2 att_avnu on att_avnu.attribute_id = att_a.id
where att_avnu.node_id in (select id from nodes2 start with code = n.code connect by prior ID = PARENTID)
) t
)
)
))
FROM NODES2 n
where n.parentID in (select id from nodes2 where code = 'TESTS')
and n.id in (select parentID from nodes2)
order by n.code asc;
Запрос работает, как и ожидалось, когда я удаляю DISTINCT. Однако он имеет дубликаты, потому что есть узлы, которые имеют одинаковый атрибут, но разные значения. Я попытался отфильтровать их, выбрав только атрибуты DISTINCT, однако по какой-то причине вся фильтрация перестает работать, как только я ее туда поместил, и она просто распечатывает все атрибуты.
Когда я запускаю запрос атрибутов отдельно, вручную заменяя n.code на строку, он снова работает нормально. Почему DISTINCT вызывает проблемы при выполнении запроса в целом? И как я могу это исправить? Я знаю DISTINCT и собираю их не слишком дружелюбно, но я не использовал их в одном запросе.
Сценарий и данные БД:
DROP TABLE NODES2;
DROP TABLE VALUES2;
DROP TABLE ATTRIBUTES2;
DROP TABLE ATTRIB_VALUE_NODE2;
CREATE TABLE NODES2
(
"ID" NUMBER,
"PARENTID" NUMBER,
"CODE" VARCHAR2(20)
);
CREATE UNIQUE INDEX "NODES2_PK" ON "NODES2" ("ID");
CREATE TABLE VALUES2
(
"ID" NUMBER,
"NAME" VARCHAR2(200)
);
CREATE UNIQUE INDEX "VALUES2_PK" ON "VALUES2" ("ID");
CREATE TABLE ATTRIBUTES2
(
"ID" NUMBER,
"NAME" VARCHAR2(200)
);
CREATE UNIQUE INDEX "ATTRIBUTES2_PK" ON "ATTRIBUTES2" ("ID");
CREATE TABLE "ATTRIB_VALUE_NODE2"
(
"ATTRIBUTE_ID" NUMBER NOT NULL,
"ATTRIB_VALUE_ID" NUMBER NOT NULL,
"NODE_ID" NUMBER NOT NULL
);
INSERT INTO "NODES2" (ID, CODE) VALUES (1,'TESTS');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (2,1,'TST1');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (3,1,'TST2');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (4,1,'TST3');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (5,2,'TST1-1');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (6,2,'TST1-2');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (7,3,'TST2-1');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (8,3,'TST2-2');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (9,3,'TST2-3');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (10,4,'TST3-1');
INSERT INTO "NODES2" (ID, PARENTID, CODE) VALUES (11,4,'TST3-2');
Insert into ATTRIBUTES2 (ID,NAME) values (1,'TestAttribute');
Insert into ATTRIBUTES2 (ID,NAME) values (2,'TestAttribute2');
Insert into ATTRIBUTES2 (ID,NAME) values (3,'TestAttribute3');
Insert into ATTRIBUTES2 (ID,NAME) values (4,'TestAttribute4');
Insert into ATTRIBUTES2 (ID,NAME) values (5,'TestAttribute5');
Insert into "VALUES2" (ID,NAME) values (1,'TestValue1');
Insert into "VALUES2" (ID,NAME) values (2,'TestValue2');
Insert into "VALUES2" (ID,NAME) values (3,'TestValue3');
Insert into "VALUES2" (ID,NAME) values (4,'TestValue4');
Insert into "VALUES2" (ID,NAME) values (5,'TestValue5');
Insert into ATTRIB_VALUE_NODE2 (ATTRIBUTE_ID,ATTRIB_VALUE_ID,NODE_ID) values (1,1,5);
Insert into ATTRIB_VALUE_NODE2 (ATTRIBUTE_ID,ATTRIB_VALUE_ID,NODE_ID) values (2,2,5);
Insert into ATTRIB_VALUE_NODE2 (ATTRIBUTE_ID,ATTRIB_VALUE_ID,NODE_ID) values (1,2,6);
Insert into ATTRIB_VALUE_NODE2 (ATTRIBUTE_ID,ATTRIB_VALUE_ID,NODE_ID) values (1,3,7);
Insert into ATTRIB_VALUE_NODE2 (ATTRIBUTE_ID,ATTRIB_VALUE_ID,NODE_ID) values (3,3,8);
Insert into ATTRIB_VALUE_NODE2 (ATTRIBUTE_ID,ATTRIB_VALUE_ID,NODE_ID) values (3,4,8);
Вывод без DISTINCT:
<tns:nodes xmlns:tns="http://somenamespace.com/">
<tns:node>
<tns:code>TST1</tns:code>
<tns:attributes>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute2</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
</tns:attributes>
</tns:node>
<tns:node>
<tns:code>TST2</tns:code>
<tns:attributes>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute3</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute3</tns:name>
</tns:attribute>
</tns:attributes>
</tns:node>
<tns:node>
<tns:code>TST3</tns:code>
<tns:attributes/>
</tns:node>
</tns:nodes>
Вывод с DISTINCT:
<tns:nodes xmlns:tns="http://somenamespace.com/">
<tns:node>
<tns:code>TST1</tns:code>
<tns:attributes>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute2</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute3</tns:name>
</tns:attribute>
</tns:attributes>
</tns:node>
<tns:node>
<tns:code>TST2</tns:code>
<tns:attributes>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute2</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute3</tns:name>
</tns:attribute>
</tns:attributes>
</tns:node>
<tns:node>
<tns:code>TST3</tns:code>
<tns:attributes>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute2</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute3</tns:name>
</tns:attribute>
</tns:attributes>
</tns:node>
</tns:nodes>
ожидаемый результат:
<tns:nodes xmlns:tns="http://somenamespace.com/">
<tns:node>
<tns:code>TST1</tns:code>
<tns:attributes>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute2</tns:name>
</tns:attribute>
</tns:attributes>
</tns:node>
<tns:node>
<tns:code>TST2</tns:code>
<tns:attributes>
<tns:attribute>
<tns:name>TestAttribute</tns:name>
</tns:attribute>
<tns:attribute>
<tns:name>TestAttribute3</tns:name>
</tns:attribute>
</tns:attributes>
</tns:node>
<tns:node>
<tns:code>TST3</tns:code>
</tns:node>
</tns:nodes>