Выберите с помощью нескольких подвыборов в одной таблице с отношениями типа «родители-дети» - PullRequest
0 голосов
/ 31 января 2020

У меня есть таблица, которая содержит данные о машинах. Среди многих других есть столбцы для (уникального) номера оборудования (EMEQP #), финансовых затрат (EMCOST), текущей стоимости (EMBOOK) и ссылки на оборудование (EMLEQP). Некоторые машины состоят из нескольких других машин, они связаны путем помещения номера EMEQP «родительского» компьютера в столбец EMLEQP. EMLEQP родительского элемента иногда заполняется (своим собственным EMEQP #), но также может быть пустым. Также не у каждого родителя есть дети, но даже тогда EMLEQP можно заполнять или нет.

Вот упрощенный образец данных:

EMEQP#    |  EMLEQP  |  EMCOST  |  EMBOOK  
ACMD001   |  ACMD001 |  10      |  12  
ACMD001A  |  ACMD001 |  8       |  1  
ACMD002   |  NULL    |  10      |  12  
SLE003    |  NULL    |  11      |  5
RUP5120   |  SLE003  |  12      |  7  

Таким образом, в этом случае ACMD001, ACMD002 и SLE003 являются родительскими машинами (поскольку EMLEQP пуст или совпадает с EMEQP #. ACMD001A является дочерний элемент ACMD001 и RUP5120 дочерний элемент SLE003.

Результат запроса должен быть следующим:

EMEQP#   |  EMCOST  |  EMBOOK  
ACMD001  |  18      |  13  
ACMD002  |  10      |  12  
SLE003   |  23      |  12

Мне нужно знать общий EMCOST и EMBOOK для каждой машины, поэтому сумма parent и все дети. Сначала я попытался использовать group by в EMLEQP, но это не сработало, поскольку в родительском случае это может быть пустым.
Далее я попытался работать с подзапросом. Основной запрос выбирает всех родителей ( WHERE EMLEQP = EMEQP# OR EMLEQP = ''), а подвыбор вычисляет сумму всех машин, где EMLEQP - это EMEQP # родительского элемента (или пустой, чтобы включить родительский элемент). Вот что у меня есть для вычисления суммы EMCOST.

SELECT EMEQP#, (SELECT SUM(b.emcost) FROM uv_EQPMASFL AS b WHERE (b.emleqp = a.emeqp# AND b.emeqp# <> a.emeqp# OR b.emeqp# = a.emeqp#) 'EMCOST' FROM uv_EQPMASFL a WHERE (EMLEQP = EMEQP# or EMLEQP = '')

Этот запрос работает, но очень медленный. Для его выполнения требуется более 15 минут, и я даже не добавил к нему вторую сумму. Поскольку я не могу использовать два столбца в подзапросе, я буду нужно добавить второй подзапрос, чтобы получить вторую сумму. Наконец, мне также хотелось бы получить еще один столбец для указания количества машин, которые являются частью родительского элемента (включая родительский).

Должен быть более эффективный и эффективный способ получения этих данных, но Я не вижу, как.

Ответы [ 2 ]

1 голос
/ 31 января 2020

Легко написать это с CTE вместо nesting select, и я уверен, что он будет выполнен через секунду для примерно 10k данных, если у вас нет проблемы INDEX:

With CTE As (
    SELECT
        emleqp,
        emeqp#,
        SUM(emcost) as EMCOST
    FROM uv_EQPMASFL
    GROUP BY emleqp, emeqp#
)

SELECT
    EMEQP#, 
    b.EMCOST
FROM uv_EQPMASFL a
LEFT JOIN CTE AS b ON b.emleqp = a.emeqp#  AND b.emeqp# <> a.emeqp# OR b.emeqp# = a.emeqp#
Where a.EMLEQP = a.EMEQP# or a.EMLEQP = ''

Пожалуйста, перепроверьте условие JOIN, потому что вам нужно parenthesis для AND и OR вместе взятых.

0 голосов
/ 04 февраля 2020

После предложения @XAMT я выбрал другой подход и смог это исправить.
Для всех, кто интересуется, сначала SELECT данные, где EMLEQP не пустые (поэтому все дети и родители имеют свой собственный EMEQP # в EMLEQP, а затем UNION, что с SELECT данных, где EMLEQP пусто.
Из этого выбора я беру еще один SELECT, который я GROUP BY EMEQP #

...