Basil Pereira Ответов: 3

Как создать родителя/ребенка в таблице?


Привет,

У меня есть таблица с тремя столбцами в следующей структуре.
ContryCode	RegionCode	HotelCode
    
    IN	        DEL	        DL65
    IN	        DEL	        DL12
    IN	        AGR	        AG47
    SG    	    JAI	        JA30
    SG	        SIN	        SI21



Я хочу преобразовать эти данные в отношения между родителями и детьми. Ожидаемый результат

ID	 Value	ParentId	Parent
1	IN	    0	        
2	DEL	    1	        IN
3	DL65	2	        DEL
4	DL12	2	        DEL
5	AGR	    1	        IN
6	AG47	5	        AGR
7	SG	    0	        
8	JAI	    7	        SG
9	JA30	8	        JAI
10	SIN    	7	        SG
11	SI21	10	        SIN


Что я уже пробовал:

Я пытался управлять через Союз всеми, но результат не таков, как ожидалось, и я не могу сформировать отношения родитель-ребенок. Я также пытался использовать рекурсивный CTE, но безуспешно.

Выберите CountryCode, RegionCode, HotelCode в #Tdest
Из Dests В

Выберите отдельный код страны в качестве значения
От #Tdest A
союз всех
Выберите код страны, как неоспоримое значение
От #Tdest B
союз всех
Выберите DISTINCT HotelCode в качестве значения
От #Tdest c


Заранее спасибо.

3 Ответов

Рейтинг:
2

Maciej Los

Если вы хотите создать древовидную структуру следующим образом:

- country1
  - region1
  + region2
    - hotel1
    - hotel2
- country2
  + region1
    - hotel1
    - hotel2
  - region2
--and so on...

вы можете достичь этого с помощью приведенного ниже скрипта:

--variables (type of table)
DECLARE @hotels TABLE (CountryCode VARCHAR(10),	RegionCode VARCHAR(10),	HotelCode VARCHAR(10))
DECLARE @places TABLE(PlaceID INT, PlaceCode VARCHAR(10), ParentID INT)

--insert source data
INSERT INTO @hotels(CountryCode, RegionCode, HotelCode)
VALUES('IN', 'DEL', 'DL65'), ('IN', 'DEL', 'DL12'),
('IN', 'AGR', 'AG47'), ('SG', 'JAI', 'JA30'), ('SG', 'SIN', 'SI21')

--insert data into destination table
INSERT INTO @places(PlaceID, PlaceCode, ParentID)
SELECT T.PlaceID, T.PlaceCode, NULL AS ParentID
FROM
(
	SELECT DISTINCT ROW_NUMBER() OVER(ORDER BY Deep, PC) PlaceID, PC AS PlaceCode, Deep
	FROM 
	(
		SELECT DISTINCT CountryCode AS PC, COUNT(CountryCode) AS Cnt, 1 AS Deep
		FROM @hotels
		WHERE CountryCode IS NOT NULL 
		GROUP BY CountryCode
		UNION ALL
		SELECT DISTINCT RegionCode AS PC, COUNT(RegionCode) AS Cnt, 2 AS Deep
		FROM @hotels
		WHERE RegionCode IS NOT NULL 
		GROUP BY RegionCode
		UNION ALL
		SELECT DISTINCT HotelCode AS PC, COUNT(HotelCode) AS Cnt, 3 AS Deep
		FROM @hotels
		WHERE HotelCode IS NOT NULL 
		GROUP BY HotelCode
	) DT
) T 

--update ParentID Of RegionCode for CountryCode
UPDATE t1 SET ParentID = t2.ParentID
FROM @places t1 INNER JOIN
(
	SELECT p.PlaceID As ParentID, h.RegionCode 
	FROM @places p INNER JOIN @hotels h ON p.PlaceCode = h.CountryCode 
) t2 ON t1.PlaceCode = t2.RegionCode  

--update ParentID Of HotelCode for RegionCode
UPDATE t1 SET ParentID = t2.ParentID
FROM @places t1 INNER JOIN
(
	SELECT p.PlaceID As ParentID, h.HotelCode 
	FROM @places p INNER JOIN @hotels h ON p.PlaceCode = h.RegionCode 
) t2 ON t1.PlaceCode = t2.HotelCode  


--display hierarchical data
;WITH CTE AS
(
	SELECT 1 AS LoopNo, PlaceID, CONVERT(VARCHAR(MAX), PlaceCode) AS FullPlaceCode
	FROM @places
	WHERE ParentID IS NULL
	UNION ALL
	SELECT LoopNo + 1 AS LoopNo, p.PlaceID, CONVERT(VARCHAR(MAX), CONCAT(c.FullPlaceCode, '->',  p.PlaceCode)) AS FullPlaceCode
	FROM CTE c INNER JOIN @places p ON c.PlaceID = p.ParentID 
)
SELECT PlaceID AS LastPlaceID, FullPlaceCode AS Hierarchy
FROM 
(
	SELECT PlaceID, FullPlaceCode, DENSE_RANK() OVER(ORDER BY LoopNo DESC) AS RowNo
	FROM CTE
	--OPTION (MAXRECURSION 0)
	--uncomment above line if you'll get an error message about recursive query exceeded the number of ...
) T
WHERE RowNo = 1
ORDER BY PlaceID


Результат (последнего SELECT заявление):
LastPlaceID	Hierarchy
7	IN->AGR->AG47
8	IN->DEL->DL12
9	IN->DEL->DL65
10	SG->JAI->JA30
11	SG->SIN->SI21


Рейтинг:
0

jsc42

Тип отношений родитель/ребенок, который вы просите, является разумным, если все элементы были одинаковыми. Например, если бы у вас была база данных сотрудников, то у сотрудника был бы менеджер, менеджер также является сотрудником, и у него / нее также есть менеджер.

Однако в вашем случае вы смешиваете страны, регионы и отели, которые несовместимы. Как, например, вы могли бы узнать, что запись для DEL относится к региону, а не к стране? Что может помешать вам иметь страну, у которой есть родитель, который является отелем?

То, что вы имеете,-это простая иерархия объектов, все отношения один-ко-многим. У вас должна быть таблица стран, таблица регионов и таблица отелей. Таблица регионов должна иметь внешний ключ, указывающий на первичный ключ в таблице стран, а таблица отелей должна иметь внешний ключ, указывающий на первичный ключ в таблице регионов.


Maciej Los

Хорошо объяснил!
+5!

Но все же можно создать древовидную структуру/ иерархические данные. Смотрите мое решение.

Basil Pereira

@jsc42

Спасибо за объяснение.Я понимаю, что таблицы должны быть нормализованы, но я нахожусь в ситуации, когда мне приходится иметь дело с этим. В любом случае спасибо за Ваш вклад.

Basil Pereira

Я собираюсь попробовать ваше решение. Я ценю вашу помощь.

Рейтинг:
0

Patrice T

Цитата:
Как создать родителя/ребенка в таблице?

Вот ссылки fzew, приятного чтения:
SQL-запросы для управления иерархическими или родительско-дочерними реляционными строками в SQL Server[^]
sql server - родительская дочерняя рекурсия SQL - переполнение стека[^]
Использование родительской дочерней иерархии в SQL Server для реализации пользовательской схемы безопасности[^]
Иерархические данные (SQL Server) - SQL Server | Microsoft Docs[^]

[Обновление]
Цитата:
У меня есть таблица с тремя столбцами в следующей структуре.

При втором чтении ваши данные не имеют отношения родитель/потомок. Использование отношения родитель/потомок выполняется для рекурсивных отношений типа "is son of". Джуниор - твой сын, ты-жулик отца, твой отец-сын дедушки.
ваши данные имеют иерархический данные, такие как имя группы/подгруппа/деталь.


Basil Pereira

Я испробовал большинство этих техник. Я имею дело с каким-то необычным случаем. В любом случае спасибо, что поделились этим.