2012-02-23 48 views
5

Chúng tôi đã có yêu cầu cung cấp một số dữ liệu cho một công ty bên ngoài. Chúng chỉ yêu cầu một mẫu dữ liệu, đơn giản phải không? sai rồi.Lấy mẫu dữ liệu SQL

Đây là tiêu chí lấy mẫu của họ:

  • Tổng Số hồ sơ chia cho 720 (cỡ mẫu cần thiết) - điều này mang đến cho khoảng cách mẫu (nếu kết quả là một phần nhỏ, làm tròn xuống đến toàn bộ kế tiếp con số).

  • Giảm khoảng thời gian lấy mẫu để có điểm bắt đầu.

  • Trả lại từng bản ghi bằng cách thêm vào khoảng thời gian lấy mẫu.

VÍ DỤ:

  • 10.000 Records - khoảng thời gian lấy mẫu = 13 (10.000/720)
  • Starting Point = 6 (13/2 Tròn)
  • hồ sơ Return 6, 19 (6 + 13), 32 (19 + 13), 45 (32 + 13) vv .....

Hãy có thể ai đó cho tôi biết thế nào (nếu) một cái gì đó như thế này là có thể trong SQL.

+0

Nhãn hiệu của SQL là gì? Nếu bạn có ROW_NUMBER() sẽ giúp ích rất nhiều. Ngoài ra, có khoảng thời gian lấy mẫu là 720 và điểm bắt đầu được xác định *** ngụ ý *** dữ liệu có thứ tự - Vì vậy, dữ liệu của bạn sẽ xuất hiện theo thứ tự nào? – MatBailie

+0

ROW_NUMBER() OVER (Sắp xếp theo TransactionDate) AS RowNumber, –

Trả lời

2

Nếu bạn sử dụng ROW_NUMBER(), thì bạn có thể thực hiện việc này tương đối dễ dàng.

ROW_NUMBER() cung cấp cho tất cả dữ liệu của bạn một số nhận dạng tuần tự (điều này quan trọng vì trường id phải là duy nhất và KHÔNG CÓ BẤT K g khoảng trống). Nó cũng xác định thứ tự bạn muốn dữ liệu trong (ORDER BY a, b, c, d).

Với id đó, nếu bạn sử dụng Modulo (thường là toán tử %), bạn có thể kiểm tra nếu bản ghi là bản ghi 720, bản ghi 1440, v.v ... (vì 720% 720 = 0).

Sau đó, nếu bạn bù đắp giá trị id của mình lên 360, bạn có thể thay đổi điểm bắt đầu của tập kết quả.

EDIT

Sau khi đọc câu hỏi, tôi thấy bạn không muốn mọi kỷ lục 720, nhưng được lựa chọn thống nhất 720 hồ sơ.

Như vậy, thay 720 với (SELECT COUNT(*)/720 FROM yourTable)

Và thay 360 với (SELECT (COUNT(*)/720)/2 FROM yourTable)

EDIT

Bỏ qua những điều kiện làm tròn sẽ cho phép một kết quả chính xác 720 hồ sơ. Điều này đòi hỏi phải sử dụng các giá trị không nguyên, và kết quả của modulo nhỏ hơn 1.

WHERE 
    (record_id + (SELECT COUNT(*) FROM yourTable)/1440.0) 
    % 
    ((SELECT COUNT(*) FROM yourTable)/720.0) 
    < 
    1.0 
+0

OK.So tôi chạy truy vấn của mình trên dữ liệu tôi đã thu thập để trả lại - Điều này cho tôi 9353 bản ghi. Khoảng thời gian lấy mẫu phải là 12, điểm bắt đầu phải là 6. Khi tôi thêm mã của bạn vào, tôi nhận được 779 hàng trả về, bất kỳ ý tưởng nào? –

+0

@Richard - 779 hàng là do yêu cầu của bạn để làm tròn khoảng mẫu xuống đến một số nguyên. '9353/720 = 12,99' =>' 12'. Sau đó, '9353/12 = 779.33' => '779'. Bạn có biết phần nào là quan trọng nhất không? Làm tròn khoảng mẫu xuống, hoặc trả về chính xác 720 bản ghi? *** [Không thể có cả hai.] *** – MatBailie

+0

Từ Yêu cầu dữ liệu, tôi sẽ nói rằng 720 là mục tiêu. –

1
declare @sample_size int, @starting_point int 

select @sample_size = 200 

select top (@sample_size) col1, col2, col3, col4 
from (
    select *, row_number() over (order by col1, col2) as row 
    from your_table 
) t 
where (row % ((select count(*) from your_table)/@sample_size)) - (select count(*) from your_table)/@sample_size/2) = 0 

Nó sẽ làm việc trong SQL Server 2005 +.

TOP (@variable) được sử dụng để giới hạn hàng (where điều kiện do số nguyên làm tròn có thể không đủ, có thể trả về nhiều hàng hơn) và ROW_NUMBER() cho số và thứ tự hàng.

dụ làm việc: http://data.stackexchange.com/stackoverflow/query/62315/sql-data-sampling dưới mã:

declare @tab table (id int identity(1,1), col1 varchar(3), col2 varchar(3)) 

declare @i int 

set @i = 0 

while @i <= 1000 
begin 
    insert into @tab 
    select 'aaa', 'bbb' 
    set @i = @i+1 
end 

declare @sample_size int 

select @sample_size = 123 

select ((select count(*) from @tab)/@sample_size) as sample_interval 

select top (@sample_size) * 
from (
    select *, row_number() over (order by col1, col2, id desc) as row 
    from @tab 
) t 
where (row % ((select count(*) from @tab)/@sample_size)) - ((select count(*) from @tab)/@sample_size/2) = 0 
+0

Tôi tự hỏi tại sao "-1", bạn có thể giải thích? có lẽ tôi học một cái gì đó mới. –

+0

Giải pháp của bạn là tốt, nhưng lý do I -1 là nó không phải là một cách tiếp cận năng động. SP sẽ thực sự tính toán điểm bắt đầu. –

+0

@Richard, ok, đọc sai nhưng dễ sửa và sửa. –

-1

Bạn có thể dùng cấp bậc để có được một hàng-số. Đoạn mã sau sẽ tạo 10000 bản ghi trong một bảng, sau đó chọn thứ 6, 19, 32, v ... cho tổng số 769 hàng.

CREATE TABLE Tbl (
    Data varchar (255) 
) 
GO 

DECLARE @i int 
SET @i = 0 
WHILE (@i < 10000) 
BEGIN 
    INSERT INTO Tbl (Data) VALUES (CONVERT(varchar(255), NEWID())) 
    SET @i = @i + 1 
END 
GO 

DECLARE @interval int 
DECLARE @start int 
DECLARE @total int 
SELECT @total = COUNT(*), 
     @start = FLOOR(COUNT(*)/720)/2, 
     @interval = FLOOR(COUNT(*)/720) 
FROM Tbl 

PRINT 'Start record: ' + CAST(@start as varchar(10)) 
PRINT 'Interval: ' + CAST(@interval as varchar(10)) 

SELECT rank, Data 
FROM (
    SELECT rank() 
    OVER (ORDER BY t.Data) as rank, t.Data AS Data 
    FROM Tbl t) q 
WHERE ((rank + 1) + @start) % @interval = 0 
+0

Tại sao RANK()? Trong trường hợp các bản ghi có cùng giá trị xếp hạng, điều này sẽ gây ra xung đột và nhiều giá trị với cùng một RANK(). Điều này có thể dẫn đến cả hai lựa chọn quá nhiều (nhiều giá trị với một RANK() quan tâm) và thiếu lựa chọn (Thiếu thứ hạng do xếp hạng đó thực sự là một tie tại một vị trí khác). Chỉ cần sử dụng ROW_NUMBER()? – MatBailie

0

Máy chủ SQL có chức năng dựng sẵn cho nó.
SELECT FirstName, LastName FROM Person.Person TABLESAMPLE (10 PERCENT);

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