2009-06-06 119 views
39

Tôi muốn nhận được chức năng của CONNECT BY PRIOR của ORACLE trong SQL SERVER 2000/2005/2008?Mô phỏng CONNECT BY PRIOR của ORACLE trong SQL SERVER

Vui lòng giúp tôi

+0

Vì bạn dường như muốn biết thêm chi tiết, bạn sẽ phải cho chúng tôi biết một số dữ liệu cấu trúc bảng và những gì bạn đang cố gắng làm. Nếu bạn có truy vấn Oracle hiện có, đó sẽ là một khởi đầu tốt .... –

+2

@ John, hãy xem URL tôi đã đăng trong câu trả lời của tôi, http://www.ibm.com/developerworks/db2/library/techarticle/ dm-0510rielau/- nó cho thấy CONNECT BY PRIOR hoạt động như thế nào (một cú pháp đẹp và độc quyền của Oracle để nhận cấu trúc cây) và cách để có được hiệu ứng tương tự với các biểu thức bảng chung (đệ quy), đó là từ khóa WITH (đó là một tiêu chuẩn SQL và được triển khai trong IBM DB2, Microsoft SQL Server và công cụ PostgreSQL mã nguồn mở trong bản phát hành 8.4). –

+0

@ Alex: cảm ơn, tôi đã xem bài đăng của bạn và đọc bài viết. Bài viết khá hay và tôi có thể thấy lý do tại sao người dùng Oracle có thể thích cú pháp Oracle. Tôi thích cú pháp chuẩn, vì nó tổng quát hơn. –

Trả lời

59

Cách chuẩn SQL để triển khai truy vấn đệ quy, như được triển khai, ví dụ: bởi IBM DB2 và SQL Server, là mệnh đề WITH. Xem this article cho một ví dụ về dịch CONNECT BY thành một WITH (về mặt kỹ thuật là CTE đệ quy) - ví dụ là dành cho DB2 nhưng tôi tin rằng nó cũng hoạt động trên SQL Server.

Chỉnh sửa: dường như querant gốc yêu cầu một ví dụ cụ thể, đây là một ví dụ từ trang web IBM có URL mà tôi đã cung cấp. Cho một bảng:

CREATE TABLE emp(empid INTEGER NOT NULL PRIMARY KEY, 
       name VARCHAR(10), 
       salary DECIMAL(9, 2), 
       mgrid INTEGER); 

nơi tham khảo mgrid người quản lý empid của một nhân viên, nhiệm vụ là, có được tên của tất cả mọi người báo cáo trực tiếp hoặc gián tiếp đến Joan. Trong Oracle, đó là một đơn giản CONNECT:

SELECT name 
    FROM emp 
    START WITH name = 'Joan' 
    CONNECT BY PRIOR empid = mgrid 

Trong SQL Server, IBM DB2, hoặc PostgreSQL 8.4 (cũng như trong tiêu chuẩn SQL, cho những gì mà đáng ;-), giải pháp hoàn hảo tương đương là thay vì một đệ quy truy vấn (cú pháp phức tạp hơn, nhưng, trên thực tế, thậm chí nhiều sức mạnh và tính linh hoạt):

WITH n(empid, name) AS 
    (SELECT empid, name 
    FROM emp 
    WHERE name = 'Joan' 
     UNION ALL 
    SELECT nplus1.empid, nplus1.name 
    FROM emp as nplus1, n 
    WHERE n.empid = nplus1.mgrid) 
SELECT name FROM n 

START WITH khoản của Oracle trở thành người đầu tiên lồng nhau SELECT, trường hợp cơ sở của đệ quy, để được UNION ed với phần đệ quy đó là chỉ một số khác là SELECT.

Hương vị cụ thể của Máy chủ SQL là WITH là khóa học được ghi lại trên MSDN, cũng cung cấp nguyên tắc và giới hạn cho việc sử dụng từ khóa này, cũng như một số ví dụ.

+1

Vui lòng giải thích bằng một ví dụ. Ví dụ: Đi một số quốc gia và khẳng định Giống như Ấn Độ --State1 - State2 Úc --AusState1 --AusStae2 Tôi đang tìm kiếm truy vấn chính xác –

+2

Ví dụ mà tôi đã chỉ ra, tại URL http://www.ibm.com/developerworks/db2/library/techarticle/dm-0510rielau/, cung cấp cho các truy vấn chính xác - sao chép nó ở đây có vẻ vô nghĩa khi bạn chỉ có thể nhấp vào liên kết! -) –

+0

** F ** phần tại [url này] (https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql) là những gì tôi đang tìm kiếm. –

1

Tôi chưa sử dụng kết nối trước đó, nhưng tìm kiếm nhanh cho thấy nó được sử dụng cho cấu trúc cây. Trong SQL Server, bạn sử dụng các biểu thức bảng chung để có được chức năng tương tự.

+2

Vui lòng giải thích bằng một ví dụ. Ví dụ: Đi một số quốc gia và khẳng định Giống như Ấn Độ --State1 - State2 Úc --AusState1 --AusStae2 –

10

@Alex Martelli Câu trả lời là tuyệt vời! Nhưng nó hoạt động chỉ dành cho một yếu tố lúc (WHERE name = 'Joan') Nếu bạn đưa ra mệnh đề WHERE, truy vấn sẽ trả lại tất cả các hàng gốc với nhau ...

tôi đã thay đổi một chút cho hoàn cảnh của tôi, vì vậy nó có thể hiển thị toàn bộ cây cho một bảng.

bảng định nghĩa:

CREATE TABLE [dbo].[mar_categories] ( 
    [category] int IDENTITY(1,1) NOT NULL, 
    [name]  varchar(50) NOT NULL, 
    [level]  int NOT NULL, 
    [action] int NOT NULL, 
    [parent] int NULL, 
    CONSTRAINT [XPK_mar_categories] PRIMARY KEY([category]) 
) 

(level là nghĩa đen mức của một loại 0: root, 1: Trình độ đầu tiên sau khi root, ...)

và truy vấn:

WITH n(category, name, level, parent, concatenador) AS 
(
    SELECT category, name, level, parent, '('+CONVERT(VARCHAR (MAX), category)+' - '+CONVERT(VARCHAR (MAX), level)+')' as concatenador 
    FROM mar_categories 
    WHERE parent is null 
     UNION ALL 
    SELECT m.category, m.name, m.level, m.parent, n.concatenador+' * ('+CONVERT (VARCHAR (MAX), case when ISNULL(m.parent, 0) = 0 then 0 else m.category END)+' - '+CONVERT(VARCHAR (MAX), m.level)+')' as concatenador 
    FROM mar_categories as m, n 
    WHERE n.category = m.parent 
) 
SELECT distinct * FROM n ORDER BY concatenador asc 

(Bạn không cần phải nối các lĩnh vực level, tôi đã chỉ để làm cho dễ đọc hơn)

câu trả lời cho truy vấn này nên được một cái gì đó như:

sql return

Tôi hy vọng nó sẽ giúp ai đó!

bây giờ, tôi tự hỏi làm thế nào để làm điều này trên MySQL ... ^^

+0

tôi đã có một vấn đề kỳ lạ thích nghi với mã của bạn, với một phi các kiểu dữ liệu tương tự trên delimiter và đệ quy cột .... nhưng nó được sắp xếp ra, chỉ với xác định chiều dài đầu tiên một cách rõ ràng .... nhờ sự giúp đỡ! –

+0

Có thể tránh việc xây dựng đường dẫn từ chuỗi ('concatenador') để có được cấu trúc giống cây (vì vậy mỗi giá trị của lá phụ được nhóm lại với nhau mà không có lỗ hổng bởi các phần tử khác)? Oracle 'connect by' xây dựng theo cách như vậy miễn phí. – gavenkoa

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