внутреннее соединение корня дерева с таблицей - PullRequest
0 голосов
/ 15 мая 2019

Итак, у меня в основном две таблицы.

|   id   | marketGroupID |
|--------|---------------|
|   1    |      134      |
|   2    |      868      |
|   3    |      387      |

второй стол:

| marketGroupid | parentGroupID |
|---------------|---------------|
|   134         |      5987     |
|   5987        |      NULL     |
|   868         |      8796     |
|   8796        |      387      |
|   387         |      NULL     |

Конечный результат должен выглядеть следующим образом:

|   id   | marketGroupID | parentGroupID |
|--------|---------------|---------------|
|   1    |      134      |     5987      |
|   2    |      868      |     387       |
|   3    |      387      |     387       |

Теперь я знаю, как ВХОДИТЬ В обе таблицы через

SELECT table1.id,table1.marketGroupID,table2.parentGroupID FROM 'table1' INNER JOIN 'table2' ON table1.marketGroupID=table2.marketGroupID;

Теперь проблема в том, что это покажет только непосредственный родитель. Но я хочу корневой родитель. Я не знаю, сколько узлов будет между корневым родителем и ребенком. Все, что я знаю, это то, что корневой родительский объект достигается, когда parentGroupID равен NULL. Корневой родитель может уже быть marketGroupID, как в случае с id = 3, или между ними может быть 3 узла, как с id = 2.

Дело в том, что я не хочу промежуточных шагов. Первый ответ в «Дубликате» делает именно это. Кроме того, он предполагает максимальное количество промежуточных шагов. Для каждого шага есть еще одно левое соединение. Я также не знаю, на каком уровне окажется корневой родитель, так как я не знаю, сколько промежуточных шагов у меня есть. Поэтому мне придется проходить каждую строку слева направо, пока не встретится ноль и последнее значение перед этим.

Ответы, использующие cte, предполагают только одну таблицу. Но у меня тоже есть таблицы. И я до сих пор хочу только корневого родителя, ничего промежуточного.

Технически, мне даже не нужен оригинальный идентификатор группы рынка. Для каждого идентификатора в таблице один мне просто нужен корневой parentgroupid и все.

1 Ответ

1 голос
/ 16 мая 2019

Это классический случай использования рекурсивного CTE .

. Начните с того, который генерирует набор строк для каждого идентификатора в первой таблице, которая проходит через все родительские цепочки:

WITH RECURSIVE parents(id, child, parent) AS
  (SELECT id, NULL, marketGroupID FROM table1
  UNION ALL
   SELECT p.id, p.parent, t2.parentGroupID
   FROM table2 AS t2
   JOIN parents AS p ON p.parent = t2.marketGroupID)
SELECT * FROM parents;
id          child       parent
----------  ----------  ----------
1                       134
2                       868
3                       387
1           134         5987
2           868         8796
3           387
1           5987
2           8796        387
2           387

В этих результатах строки с нулевым дочерним столбцом являются идентификаторами базовой группы, строки со значениями в обоих столбцах являются промежуточными в цепочке ссылок на корень, а строки с нулевымродительский столбец имеет окончательный корневой идентификатор группы для каждой строки table1.Это последний набор строк, который нас интересует. Добавление отслеживания исходных дочерних групп и фильтрации некорневых строк дает окончательные результаты:

WITH RECURSIVE parents(id, market, child, parent) AS
  (SELECT id, marketGroupID, NULL, marketGroupID FROM table1
  UNION ALL
   SELECT p.id, p.market, p.parent, t2.parentGroupID
   FROM table2 AS t2
   JOIN parents AS p ON p.parent = t2.marketGroupID)
SELECT id, market AS marketGroupID, child AS parentGroupID
FROM parents
WHERE parent IS NULL
ORDER BY id;
id          marketGroupId  parentGroupID
----------  -------------  -------------
1           134            5987
2           868            387
3           387            387

Технически, я надеваюдаже не нужен оригинальный идентификатор группы рынка.Для каждого идентификатора в таблице один мне просто нужен корневой parentgroupid и все.

WITH RECURSIVE parents(id, child, parent) AS
  (SELECT id, NULL, marketGroupID FROM table1
  UNION ALL
   SELECT p.id, p.parent, t2.parentGroupID
   FROM table2 AS t2
   JOIN parents AS p ON p.parent = t2.marketGroupID)
SELECT id, child AS parentGroupID FROM parents WHERE parent IS NULL ORDER BY ID;
...