Pracuję na bazie danych zasobów, który ma hierarchii. Istnieje również tabela "ReferenceAsset", która skutecznie wskazuje na zasób. Zasób referencyjny zasadniczo działa jako nadpisanie, ale jest wybierany tak, jakby był unikalnym, nowym zasobem. Jednym z nadpisań, które zostaną ustawione, jest parent_id.Serwer SQL: kwerenda danych hierarchicznych i odniesienia
Kolumny, które są istotne dla wyboru heirarchy:
Zaleta: id (pierwotne), parent_id
aktywa referencyjnego: Identyfikator (podstawowej), asset_id (foreignkey-> aktywami), parent_id (zawsze atutem)
- --EDITED 5/27 ----
próbki dowiemy się z tabeli danych (po dołącza)
id | asset_id | name | parent_id | milestone | type 3 3 suit null march shape 4 4 suit_banker 3 april texture 5 5 tie null march shape 6 6 tie_red 5 march texture 7 7 tie_diamond 5 june texture -5 6 tie_red 4 march texture
id < 0 (jak ostatni wiersz) oznacza aktywa, do których się odwołuje. Zasoby z odniesieniami mają kilka kolumn, które są nadpisane (w tym przypadku ważny jest tylko identyfikator nadrzędny).
Oczekuje się, że jeśli wybiorę wszystkie aktywa od kwietnia, należy zrobić wtórny wybierz, aby uzyskać całe gałęzie drzewa zapytania Dopasowanie:
więc początkowo mecz zapytanie spowodowałoby:
4 4 suit_banker 3 april texture
Następnie po CTE, otrzymujemy pełną hierarchię, a nasz wynik powinien być to (jak dotąd to działa)
3 3 suit null march shape 4 4 suit_banker 3 april texture -5 6 tie_red 4 march texture
i widać, rodzicem ID: -5 tam jest, ale czego brakuje, co jest potrzebne, jest określany aktywami, a dominującą odwołuje aktywów:
5 5 tie null march shape 6 6 tie_red 5 march texture
Obecnie moje rozwiązanie działa w tym celu, ale ogranicza się tylko do jednej głębokości referencji (i uważam, że wdrożenie jest dość brzydkie).
--- Edytowany ---- Oto moja podstawowa funkcja wyboru. Powinno to lepiej pokazać, gdzie leży prawdziwa komplikacja: AssetReference.
Select A.id as id, A.id as asset_id, A.name,A.parent_id as parent_id, A.subPath, T.name as typeName, A2.name as parent_name, B.name as batchName,
L.name as locationName,AO.owner_name as ownerName, T.id as typeID,
M.name as milestoneName, A.deleted as bDeleted, 0 as reference, W.phase_name, W.status_name
FROM Asset as A Inner Join Type as T on A.type_id = T.id
Inner Join Batch as B on A.batch_id = B.id
Left Join Location L on A.location_id = L.id
Left Join Asset A2 on A.parent_id = A2.id
Left Join AssetOwner AO on A.owner_id = AO.owner_id
Left Join Milestone M on A.milestone_id = M.milestone_id
Left Join Workflow as W on W.asset_id = A.id
where A.deleted <= @showDeleted
UNION
Select -1*AR.id as id, AR.asset_id as asset_id, A.name, AR.parent_id as parent_id, A.subPath, T.name as typeName, A2.name as parent_name, B.name as batchName,
L.name as locationName,AO.owner_name as ownerName, T.id as typeID,
M.name as milestoneName, A.deleted as bDeleted, 1 as reference, NULL as phase_name, NULL as status_name
FROM Asset as A Inner Join Type as T on A.type_id = T.id
Inner Join Batch as B on A.batch_id = B.id
Left Join Location L on A.location_id = L.id
Left Join Asset A2 on AR.parent_id = A2.id
Left Join AssetOwner AO on A.owner_id = AO.owner_id
Left Join Milestone M on A.milestone_id = M.milestone_id
Inner Join AssetReference AR on AR.asset_id = A.id
where A.deleted <= @showDeleted
Mam procedura składowana, która pobiera tabelę temp (#temp) i znajduje wszystkie elementy hierarchii.Strategia I zatrudnionych było to:
- Zaznacz cały heirarchy system w tabeli temp (#treeIDs) reprezentowane przez oddzielone przecinkami liście każdego całej gałęzi drzewa
- Pobierz całą heirarchy aktywów pasujących rekordów (od # temp)
- Uzyskaj wszystkie aktywa referencyjne wskazywanego przez aktywa z heirarchy
- Analizować heirarchy wszystkich aktywów referencyjnych
działa to na razie, ponieważ aktywa referencyjne są zawsze la element na gałęzi, ale jeśli nie, myślę, że będę miał kłopoty. Czuję, że potrzebuję lepszej formy rekurencji.
Tu jest mój bieżący kod, który działa, ale nie jestem z niego dumny, i wiem, że to nie jest mocny (ponieważ działa tylko wtedy, gdy występują odnośniki na dole):
Krok 1. zbudować całą hierarchię
;WITH Recursive_CTE AS (
SELECT Cast(id as varchar(100)) as Hierarchy, parent_id, id
FROM #assetIDs
Where parent_id is Null
UNION ALL
SELECT
CAST(parent.Hierarchy + ',' + CAST(t.id as varchar(100)) as varchar(100)) as Hierarchy, t.parent_id, t.id
FROM Recursive_CTE parent
INNER JOIN #assetIDs t ON t.parent_id = parent.id
)
Select Distinct h.id, Hierarchy as idList into #treeIDs
FROM (Select Hierarchy, id FROM Recursive_CTE) parent
CROSS APPLY dbo.SplitIDs(Hierarchy) as h
Krok 2. Wybierz gałęzie wszystkich aktywów pasujących zapytaniu
Select DISTINCT L.id into #RelativeIDs FROM #treeIDs
CROSS APPLY dbo.SplitIDs(idList) as L
WHERE #treeIDs.id in (Select id FROM #temp)
Krok 3. Pobierz wszystkie aktywa referencyjne w oddziałach (aktywa referencyjne mają ujemne wartości id, stąd część id < 0)
Select asset_id INTO #REFLinks FROM #AllAssets WHERE id in
(Select #AllAssets.asset_id FROM #AllAssets Inner Join #RelativeIDs
on #AllAssets.id = #RelativeIDs.id Where #RelativeIDs.id < 0)
Krok 4. Pierwsze oddziały cokolwiek znaleźć w kroku 3
Select DISTINCT L.id into #extraRelativeIDs FROM #treeIDs
CROSS APPLY dbo.SplitIDs(idList) as L
WHERE
exists (Select #REFLinks.asset_id FROM #REFLinks WHERE #REFLinks.asset_id = #treeIDs.id)
and Not Exists (select id FROM #RelativeIDs Where id = #treeIDs.id)
Starałem się po prostu pokazać odpowiedni kod. Jestem bardzo wdzięczny każdemu, kto może mi pomóc znaleźć lepsze rozwiązanie!
jakiej używasz wersji sql? http://msdn.microsoft.com/de-de/library/bb677290.aspx – NickD
serwer sql 2012, ale przełączyliśmy się na niego, więc większość z tego została napisana na rok 2008 – haggercody