Итак, вот и все.
Я пишу запрос для клиента, чтобы визуализировать данные, которые он заполнил, для веб-форм, которые мы для него создали. Структура форм может состоять из нескольких вложенных записей (назовем их дочерними) к основной записи (назовем это родительской). Все дети имеют свои собственные формы, с разными полями и отдельно от родителя. Прямо сейчас наши данные хранятся таким образом, что данные из всех форм хранятся в одной и той же таблице, разделенной «идентификатором записи», который уникален для каждой заполняемой формы, и «идентификатором сущности», которая указывает, к какой именно форме принадлежат данные (будь то родитель или один из детей).
У нас есть отдельная таблица, в которой мы сохраняем все наши отношения.
Прямо сейчас мне нужно написать запрос, который соответствует отношению дочерних записей к родительской записи. У меня есть несколько дочерних форм внутри родительской формы, поэтому вы увидите Child_1 и Child_2. Клиент хочет, чтобы данные были как можно более сжатыми ... поэтому мы начали для них разделять данные, чтобы в одной строке у вас был Parent_Data_1, а затем первая запись во всех дочерних формах. Следующей строкой будет тот же Родитель СНОВА, ЕСЛИ есть вторая запись в одной из дочерних форм. Это будет продолжаться go до тех пор, пока в конкретном родительском элементе больше не будет дочерних форм, и следующая строка будет следующим Родителем (Родителем 2), выровненным по первой записи дочернего элемента в Родителе 2 и т. Д. И т. Д. ,
Это ЗНАЧИТЕЛЬНО замедляет время выполнения запроса. Я прошел секунд за 20 000 строк до 30 минут. У нас есть функциональность, позволяющая клиенту запускать «фильтры» в своих данных, поэтому они запускают запрос несколько раз в неделю, чтобы получить данные, которые они ищут ... но это не может занять столько времени, сколько это необходимо. сейчас же.
Есть какие-нибудь предложения?
Final Basi c Пример:
Row 1: Parent_Data_1 ... Child_1_Record_1_Data ... Child_2_Record_1_Data
Row 2: Parent_Data_1 ... Child_1_Record_2_Data ... Null (if there isn't more than one record for Child Form)
Row 3: Parent_Data_2 ... Child_1_Record_3_Data ... Child_2_Record_2_Data
Row 4: Parent_Data_2 ... Null ... Child 2_Record_3_Data
Row 5: Parent_Data_3 ... Child_1_Record_4_Data ... Child 2_Record_4_Data
Row 6: Parent_Data_3 ... Child_1_Record_5_Data ... Child 2_Record_5_Data
Row 7: Parent_Data_3 ... Child_1_Record_6_Data ... Null
Ниже приведены скелеты моих таблиц и урезанная версия запроса, который я использую:
Dat_Data_Lrg:
+--------------------+--------------------+--------+--------+-------------+
| Entity_ID | Record_ID | Data_1 | Data_2 | Entity_TYPE |
+--------------------+--------------------+--------+--------+-------------+
| Parent_Entity_ID | Parent_Record_ID | 123 | 456 | 2500 |
| Child_Entity_ID_1 | Child_Record_ID_1 | 223 | 556 | 2500 |
| Child_Entity_ID_2 | Child_Record_ID_2 | 323 | 656 | 2500 |
| Parent_Entity_ID_2 | Parent_Record_ID_2 | 423 | 756 | 2500 |
| Child_Entity_ID_1 | Child_Record_ID_3 | 523 | 856 | 2500 |
+--------------------+--------------------+--------+--------+-------------+
ref_references:
+--------------------+--------------------+--------------------+-------------------+
| Entity_ID_Parent | Record_ID_Parent | Entity_ID_Child | Record_ID_Child |
+--------------------+--------------------+--------------------+-------------------+
| Parent_Entity_ID | Parent_Record_ID | Child_Entity_ID_1 | Child_Record_ID_1 |
| Parent_Entity_ID | Parent_Record_ID | Child_Entity_ID_2 | Child_Record_ID_2 |
| Parent_Entity_ID | Parent_Record_ID | Child_Entity_ID_1 | Child_Record_ID_3 |
+--------------------+--------------------+--------------------+-------------------+
Dat_Record:
+--------------------+--------------------+--------------+----------------+--------+
| Entity_ID | Record_ID | Entity_Type | Entity_Token | STATE |
+--------------------+--------------------+--------------+----------------+--------+
| Parent_Entity_ID | Parent_Record_ID | 2500 | Parent_Token | 2 |
| Child_Entity_ID | Child_Record_ID | 2500 | Child_Token | 2 |
| Child_Entity_ID_2 | Child_Record_ID_2 | 2500 | Child_Token_2 | 2 |
| Parent_Entity_ID_2 | Parent_Record_ID_2 | 2500 | Parent_Token | 2 |
| Child_Entity_ID | Child_Record_ID_3 | 2500 | Child_Token | 2 |
+--------------------+--------------------+--------------+----------------+--------+
Финальный стол
SELECT
A.RecID as RecID,
A.Parent_Data_1 as Parent_Data_1,
A.Parent_Data_2 as Parent_Data_2,
Child_Detail.Child_1_Data_1 as Child_1_Data_1,
Child_Detail.Child_1_Data_2 as Child_1_Data_2,
Child_Detail.Child_2_Data_1 as Child_2_Data_1,
Child_Detail.Child_2_Data_2 as Child_2_Data_2,
FROM (
select
ROW_NUMBER() OVER(Partition by inc.recid ORDER BY inc.recid) as rn,
inc.recid as RecID,
dddl1.Parent_Data_1 as Parent_Data_1,
dddl1.Parent_Data_2 as Parent_Data_2,
from
Dat_Record inc, Dat_Data_Lrg dddl1
where
inc.Entity_TYPE = 2500 and inc.Entity_Token = 'SPILL_RECORDS' and inc.state < 3
and dddl1.Entity_TYPE = inc.Entity_TYPE and dddl1.Entity_ID = inc.Entity_ID
dddl1.Record_ID = inc.Record_ID
) as A OUTER APPLY
( select n,
B.Child_1_Data_1,
B.Child_1_Data_2,
C.Child_2_Data_1,
C.Child_2_Data_2
from ( select mn.n, dr.Record_ID from msc_nums mn, dat_record dr where dr.Record_ID = A.RecID and
mn.n < = (select max(rw) from (select count(*) rw from ref_references where Record_ID_Parent = dr.Record_ID group by Entity_ID_Child) as t1)
) AS SP
LEFT JOIN (
SELECT distinct
ROW_NUMBER() OVER(Partition by illref.Record_ID_Parent ORDER BY illref.Record_ID_Child) as rn,
inc.Record_ID as RecID,
dddl2.Data_1 as Child_1_Data_1,
dddl2.Data_2 as Child_1_Data_2
from
Dat_Record inc, Dat_Record ill, ref_references illref,
Dat_Data_Lrg dddl2
where
inc.Entity_TYPE = 2500 and inc.Entity_Token = 'SPILL_RECORDS' and inc.state < 3
and illref.Entity_ID_Child = 'Child_Entity_ID_1' and illref.Record_ID_Parent = inc.Record_ID
and ill.Entity_TYPE = 2500 and ill.Entity_Token = 'Child_Token' and ill.state < 3
and ill.Record_ID = illref.Record_ID_Child and ill.Record_ID = dddl2.Record_ID
and dddl2.Entity_TYPE = illref.Entity_TYPE and dddl2.Entity_ID = illref.Entity_ID_Child
and dddl2.Record_ID = illref.Record_ID_Child) as B
ON (A.RecID = B.RecID AND B.rn=SP.n)
LEFT JOIN (
SELECT distinct
ROW_NUMBER() OVER(Partition by illref.Record_ID_Parent ORDER BY illref.Record_ID_Child) as rn,
inc.Record_ID as RecID,
dddl3.Data_1 as Child_2_Data_1,
dddl3.Data_2 as Child_2_Data_2
from
Dat_Record inc, Dat_Record ill, ref_references illref,
Dat_Data_Lrg dddl3
where
inc.Entity_TYPE = 2500 and inc.Entity_Token = 'SPILL_RECORDS' and inc.state < 3
and illref.Entity_ID_Child = 'Child_Entity_ID_2' and illref.Record_ID_Parent = inc.Record_ID
and ill.Entity_TYPE = 2500 and ill.Entity_Token = 'Child_Token_2' and ill.state < 3
and ill.Record_ID = illref.Record_ID_Child and ill.Record_ID = dddl3.Record_ID
and dddl3.Entity_TYPE = illref.Entity_TYPE and dddl3.Entity_ID = illref.Entity_ID_Child
dddl3.Record_ID = illref.Record_ID_Child ) as C
ON (A.RecID = C.RecID AND C.rn = SP.n)
) AS Child_Detail