2013-04-28 33 views
6

Tôi đang làm việc trên cơ sở dữ liệu nội dung có phân cấp. Ngoài ra, có một bảng "ReferenceAsset", có hiệu quả chỉ trở lại một tài sản. Tài sản tham chiếu về cơ bản hoạt động như một ghi đè, nhưng nó được chọn như thể nó là một tài sản mới duy nhất. Một trong các ghi đè được đặt, là parent_id.Máy chủ SQL: truy vấn dữ liệu phân cấp và tham chiếu

Cột có liên quan đến việc lựa chọn các hệ thống cấp bậc:
Asset: id (tiểu học), PARENT_ID
Asset tham khảo: id (tiểu học), asset_id (foreignkey-> Asset), PARENT_ID (luôn là một tài sản)
- --EDITED 5/27 ----

mẫu có liên quan Bảng dữ liệu (sau khi tham gia):

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 

sự id < 0 (giống như hàng cuối cùng) biểu thị các tài sản được tham chiếu. Tài sản được tham chiếu có một vài cột bị ghi đè (trong trường hợp này, chỉ có parent_id là quan trọng).

Hi vọng là nếu tôi chọn toàn bộ tài sản từ tháng tư, tôi nên làm một lựa chọn thứ để có được toàn bộ cành cây của truy vấn phù hợp:

vì thế ban đầu trận đấu truy vấn sẽ cho kết quả:

4  4  suit_banker   3   april  texture 

sau đó, sau khi CTE, chúng tôi nhận được hệ thống phân cấp đầy đủ và kết quả của chúng tôi phải được điều này (cho đến nay đây là làm việc)

3  3  suit    null  march  shape 
    4  4  suit_banker   3   april  texture 
    -5  6  tie_red    4   march  texture 

và bạn thấy, phụ huynh của id: -5 là có, nhưng những gì là mất tích, đó là cần thiết, là tài sản tham chiếu, và phụ huynh của các tài sản tham chiếu:

5  5  tie    null  march  shape 
    6  6  tie_red    5   march  texture 

Hiện tại giải pháp của tôi hoạt động cho điều này, nhưng nó chỉ giới hạn ở một độ sâu tham chiếu duy nhất (và tôi cảm thấy việc triển khai khá xấu).

--- Đã chỉnh sửa ---- Đây là chức năng lựa chọn chính của tôi. Điều này sẽ chứng minh tốt hơn nơi mà các biến chứng thực sự nằm ở: 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 

Tôi có một thủ tục được lưu trữ có bảng tạm thời (#temp) và tìm tất cả các phần tử của cấu trúc phân cấp.Chiến lược tôi làm việc là thế này:

  1. Chọn hệ thống toàn bộ hệ thống cấp bậc vào một bảng tạm thời (#treeIDs) đại diện bởi một dấu phẩy tách ra danh sách của mỗi toàn bộ cành cây
  2. Nhận toàn bộ hệ thống cấp bậc của tài sản phù hợp với truy vấn (từ # temp)
  3. Nhận toàn bộ tài sản tài liệu tham khảo được trỏ đến bởi tài sản từ hệ thống cấp bậc
  4. Phân tích các hệ thống cấp bậc của toàn bộ tài sản tham khảo

này làm việc cho bây giờ bởi vì tài sản tham khảo luôn là la st mục trên một chi nhánh, nhưng nếu họ không, tôi nghĩ rằng tôi sẽ gặp rắc rối. Tôi cảm thấy như tôi cần một hình thức đệ quy tốt hơn.

Đây là mã hiện tại của tôi, mà đang làm việc, nhưng tôi không tự hào về nó, và tôi biết nó không phải là mạnh mẽ (vì nó chỉ hoạt động nếu các tài liệu tham khảo là ở phía dưới):

Bước 1. xây dựng toàn bộ hệ thống phân cấp

;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 

Bước 2. Chọn chi nhánh của toàn bộ tài sản phù hợp với truy vấn

Select DISTINCT L.id into #RelativeIDs FROM #treeIDs 
CROSS APPLY dbo.SplitIDs(idList) as L 
WHERE #treeIDs.id in (Select id FROM #temp) 

Bước 3. Nhận tất cả các tài sản tham khảo trong các ngành.210 (tài sản có giá trị tham khảo id tiêu cực, vì thế mà id < 0 phần)

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) 

Bước 4. Nhận các chi nhánh của bất cứ điều gì được tìm thấy trong bước 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) 

Tôi đã cố gắng để chỉ hiển thị các mã có liên quan. Tôi rất biết ơn bất cứ ai có thể giúp tôi tìm ra giải pháp tốt hơn!

+0

bạn đang sử dụng phiên bản sql nào? http://msdn.microsoft.com/de-de/library/bb677290.aspx – NickD

+0

máy chủ sql 2012, nhưng chúng tôi vừa chuyển sang nó, vì vậy hầu hết điều này được viết cho 2008 – haggercody

Trả lời

1
--getting all of the children of a root node (could be > 1) and it would require revising the query a bit 

DECLARE @AssetID int = (select AssetId from Asset where AssetID is null); 


--algorithm is relational recursion 
--gets the top level in hierarchy we want. The hierarchy column 
--will show the row's place in the hierarchy from this query only 
--not in the overall reality of the row's place in the table 

WITH Hierarchy(Asset_ID, AssetID, Levelcode, Asset_hierarchy) 
AS 
(
SELECT AssetID, Asset_ID, 
     1 as levelcode, CAST(Assetid as varchar(max)) as Asset_hierarchy 
FROM Asset 
WHERE [email protected] 

UNION ALL 

--joins back to the CTE to recursively retrieve the rows 
--note that treelevel is incremented on each iteration 

SELECT A.Parent_ID, B.AssetID, 
     Levelcode + 1 as LevelCode, 
     A.assetID + '\' + cast(A.Asset_id as varchar(20)) as Asset_Hierarchy 
FROM Asset AS a 
      INNER JOIN dbo.Batch AS Hierarchy 
      --use to get children, since the parentId of the child will be set the value 
      --of the current row 
      on a.assetId= b.assetID 
--use to get parents, since the parent of the Asset_Hierarchy row will be the asset, 
      --not the parent. 
      on Asset.AssetId= Asset_Hierarchy.parentID 


SELECT a.Assetid,a.name, 
     Asset_Hierarchy.LevelCode, Asset_Hierarchy.hierarchy 
FROM  Asset AS a 
     INNER JOIN Asset_Hierarchy 
       ON A.AssetID= Asset_Hierarchy.AssetID 
ORDER BY Hierarchy ; 
--return results from the CTE, joining to the Asset data to get the asset name 
---that is the structure you will want. I would need a little more clarification of your table structure 
+0

wow. rực rỡ. cảm ơn bạn! – haggercody

0

Nó sẽ giúp biết cấu trúc bảng cơ bản của bạn. Có hai cách tiếp cận sẽ hoạt động tùy thuộc vào môi trường của bạn: SQL hiểu XML để bạn có thể có SQL của bạn dưới dạng cấu trúc xml hoặc đơn giản chỉ có một bảng duy nhất với mỗi mục hàng có id khóa chính duy nhất và parentid. id là fk cho parentid. Dữ liệu cho nút chỉ là các cột tiêu chuẩn. Bạn có thể sử dụng một cte hoặc một hàm cung cấp một cột được tính toán để xác định mức độ lồng nhau cho mỗi nút. Giới hạn là một nút chỉ có thể có một phụ huynh.

+0

Cảm ơn bạn đã xem qua điều này.
Tôi đã cập nhật OP với chức năng lựa chọn, cho thấy cấu trúc bảng tốt hơn. Vấn đề thực sự là xung quanh bảng AssetReference. Hãy để tôi giải thích một tình huống cụ thể: Cân nhắc tôi chọn Tài sản theo lô hàng loạt: Tôi nhận được [BallCap] - sau đó tôi chọn toàn bộ nhánh cây cho [BallCap] (tốt cho đến nay) Nhưng sau đó tôi gặp AssetReference cây Bây giờ tôi phải chọn Tài sản gốc được tham chiếu Và sau đó tôi cần toàn bộ Cây cho Tài sản này – haggercody

+0

Bạn đang nói rằng bạn có một tập hợp các nhánh cho một nút và trên một trong những nhánh đó có thể là một nút đang bật một cây hoàn toàn khác? –

+0

có, một nút trong nhánh có thể 'tham chiếu' một nút khác có thể nằm trong nhánh cây khác. 'Tham chiếu' này là từ một bảng khác (AssetReference). Tôi đã phá vỡ một điều răn thiết kế ở đây? – haggercody

Các vấn đề liên quan