2010-07-13 32 views
5

Có một truy vấn SQL tôi có thể làm điều đó sẽ tạo ra một chuỗi tuyến tính nhưCó cách nào chung để tạo ra một chuỗi tuyến tính tùy ý trong SQL?

1, 2, 3, 4, 5, 6, 7 ... x+1 

hoặc

2, 7, 12, 17, 22 ... 2+5x 

(trong đó mỗi số là một mục trong một hàng của bảng kết quả)

+0

Có một số lý do để thực hiện điều này trong SQL thay vì ở cấp ứng dụng không? – Borealid

+1

@Borealid - Thường hữu ích khi có bảng số phụ trợ trong SQL. –

+0

@Borealid: Nếu tôi có thể tạo ra một bảng như vậy, thì tôi tin rằng tôi có thể sử dụng nó để xây dựng các truy vấn phức tạp hơn; Nếu tôi tạo ra nó trong ứng dụng, tôi nghĩ rằng tôi sẽ bị mắc kẹt với các câu lệnh SQL siêu dài với chuỗi được xây dựng trong chúng. –

Trả lời

1

No. (Trừ khi xử lý trước một bảng các số được tính như một cách chung chung.)

Trong SQL Server, điều này có thể được thực hiện với CTE đệ quy hoặc generat đệ quy ing một chuỗi sử dụng ROW_NUMBER()

0

Sử dụng chuỗi

3

SQL Server và Oracle hiện triển khai các ROW_NUMBER tiêu chuẩn ANSI() chức năng cửa sổ, nhưng bạn sẽ cần một chiếc bàn làm việc tắt của:

SELECT ROW_NUMBER() OVER (ORDER BY ID) AS __ROW, ID, Name 
FROM SomethingWithANameAndAnID 
ORDER BY __ROW; 

Hoặc bạn có thể sử dụng một biểu thức bảng chung đệ quy trong SQL Server (không chắc chắn nếu Oracle thực hiện điều này chưa):

WITH cte AS 
(
    SELECT 1 AS num 
    UNION ALL 
    SELECT (num + 1) AS num FROM cte 
    WHERE num < @SomeMaximum 
) 
SELECT * FROM cte OPTION (MAXRECURSION 0); 

Lưu ý rằng nếu không có tùy chọn MAXRECURSION CTE đệ quy sâu trong MS SQL được giới hạn 100. (giá trị từ 0 vô hiệu hóa các giới hạn đệ quy)

0

Trong Oracle, bạn có thể làm:

select ROWNUM linear_sequence from dual CONNECT BY LEVEL <= x; 

trong đó x là kết thúc của trình tự.

+0

Hoặc (đối với chuỗi biến thể của OP): chọn (ROWNUM-1) * 5 + 2 AS linear_sequence từ hai CONNECT BY LEVEL <= x; –

0

Bạn có thể chỉ định một tăng khi tạo một chuỗi:

CREATE SEQUENCE mysequence INCREMENT BY 5 START WITH 2; 
2

Nếu hiệu suất là mối quan tâm của bạn, có UDF này đã sẵn sàng:

create function [dbo].[Numbers](@count bigint) 
RETURNS TABLE RETURN 
with byte (n) as (select 1 from (VALUES 
     (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ) x(n) ) 
, byte2 (n) as (select 1 from byte a, byte b) 
, byte4 (n) as (select 1 from byte2 a, byte2 b) 
, byte8 (n) as (select 1 from byte4 a, byte4 b) 
select top(@count) n = ROW_NUMBER() over(order by n) from byte8 

Rõ ràng, đệ quy chỉ CTE tạo các công trình chuỗi số, nhưng rất chậm. Ở đây chúng tôi giao dịch một số khối lượng mã cho sự gia tăng rất lớn về hiệu suất. Điều này mang lại cho tôi hơn 30 triệu con số trong 8 giây trên máy tính bị quá tải crappy của tôi. Nó có thể đi xa như bạn muốn và có thể đủ khả năng để giới hạn của bigint tối đa.

Nó sẽ không chạm vào đĩa IO trừ khi trình tối ưu hóa loại bỏ nó ra khỏi bộ nhớ (hầu như không bao giờ cho kịch bản hợp lý). Nó cũng sẽ tránh chờ đợi và deadlocks không giống như các giải pháp dựa trên bảng vật lý.

Sử dụng như thế này:

select 2 + n*5 from Numbers(100) 

Bạn sẽ có thể tạo ra một cái nhìn như thế này.

Đối với những người không yêu cầu số thực tế, chỉ cần hàng, loại bỏ thứ row_number tăng tốc hai lần.

Lấy cảm hứng từ http://weblogs.sqlteam.com/jamesn/archive/2008/05/29/60612.aspx (Itzik Ben Gan được đề cập bởi S. Neumann). Phiên bản này đi kèm với một kế hoạch thực hiện đơn giản và làm cho bigints có thể, đó là về những lợi thế.

+0

So sánh hiệu suất với một giải pháp tương tự ở đây http://stackoverflow.com/a/16605089/481812 – Rbjz

+0

Bằng chứng có thể mất thời gian lớn bây giờ 'chọn count_big (1) từ [dbo]. [Numbers] (2147483650)' mất 2 phút – Rbjz

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