Tìm tất cả các nút tổ tiên của HVELyId bằng cách sử dụng một câu lệnh SQL?


7

Tôi đang cố gắng tìm cách để có được tất cả các nút tổ tiên của một nút đã cho bằng cách sử dụng HVELyID. Mọi giải pháp tôi từng thấy khi sử dụng HVELyID dường như sử dụng CTE hoặc biến. Có cách nào để làm điều này bằng cách sử dụng một câu lệnh chọn không?

Để làm cho mọi thứ đơn giản hơn:

CREATE TABLE Employee
(
    EmpId INT PRIMARY KEY IDENTITY,
    EmpName VARCHAR(100) NOT NULL,
    Position HierarchyID NOT NULL
)

INSERT INTO Employee (EmpName, Position)
VALUES ('CEO', '/'),
    ('COO', '/1/'),
    ('CIO', '/2/'),
    ('CFO', '/3/'),
    ('VP Financing', '/3/1/'),
    ('Accounts Receivable', '/3/1/1/'),
    ('Accountant 1', '/3/1/1/1/'),
    ('Accountant 2', '/3/1/1/2/'),
    ('Accountant 3', '/3/1/1/3/'),
    ('Accounts Payable', '/3/1/2/'),
    ('Accountant 4', '/3/1/2/1/'),
    ('Accountant 5', '/3/1/2/2/'),
    ('DBA', '/2/1/'),
    ('VP of Operations', '/1/1/')

một giải pháp CTE một tuyên bố chọn duy nhất, phải không?
Jack nói hãy thử topanswers.xyz

Nói chung, các giải pháp tôi đã thấy bằng cách sử dụng CTE là đệ quy, điều này gây nhầm lẫn. Ngoài ra, có một lựa chọn để xác định CTE (thay vì hai cho đệ quy) và một để lấy dữ liệu từ nó. Tôi đã tự hỏi nếu có một tuyên bố duy nhất có thể được thực hiện mà không cần sử dụng CTE.
Richard

Câu trả lời:


10

Để nhận "tất cả các nút cha của một nút đã cho":

select *, position.GetAncestor(1), position.GetAncestor(1).ToString()
from employee
where position=hierarchyid::Parse('/3/1/')

EmpId  EmpName       Position  (No column name)  (No column name)
5      VP Financing  0x7AC0    0x78              /3/

nhưng sẽ chỉ có một do tính chất của thứ bậc.

Nếu bạn thực sự muốn nhận tất cả các nút con ngay lập tức của một nút đã cho:

select * 
from employee 
where position.IsDescendantOf(hierarchyid::Parse('/3/1/'))=1
      and position.GetLevel()=hierarchyid::Parse('/3/1/').GetLevel()+1

EmpId  EmpName              Position
6      Accounts Receivable  0x7AD6
10     Accounts Payable     0x7ADA

-- BIÊN TẬP

Tôi thấy rằng bạn muốn tất cả các nút tổ tiên. Có lẽ hãy thử một cách tiếp cận như thế này:

select * 
from employee
where hierarchyid::Parse('/3/1/2/1/').IsDescendantOf(Position) = 1

hoặc là

select * from employee
where ( select position 
        from employee 
        where empname='Accountant 4' ).IsDescendantOf(Position) = 1

đây là một phương pháp CTE để so sánh:

with w as ( select * from employee where empname='Accountant 4'
            union all
            select e.*
            from employee e join w on(w.position.GetAncestor(1)=e.Position) )
select * from w;

Tôi thực sự thích những thứ đó. Chúng rất sạch sẽ và dễ hiểu. Tốt hơn nhiều so với những gì tôi đã nghĩ ra.
Richard
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.