Tôi đã thấy nhiều cách sử dụng khi bạn cần chiếu 'dữ liệu bị thiếu'. Ví dụ. bạn có một chuỗi thời gian (ví dụ: nhật ký truy cập) và bạn muốn hiển thị số lần truy cập mỗi ngày trong 30 ngày qua (nghĩ bảng điều khiển phân tích). Nếu bạn làm một select count(...) from ... group by day
bạn sẽ nhận được số lượng mỗi ngày, nhưng kết quả sẽ chỉ có một hàng cho mỗi ngày bạn thực sự có ít nhất một truy cập. Mặt khác, nếu bạn lần đầu tiên chiếu một bảng ngày từ bảng số của bạn ( select dateadd(day, -number, today) as day from numbers
) và sau đó bạn rời khỏi tham gia với số đếm (hoặc áp dụng bên ngoài, bất cứ điều gì bạn thích) thì bạn sẽ nhận được kết quả có 0 cho số ngày bạn không có quyền truy cập. Đây chỉ là một ví dụ. Tất nhiên, người ta có thể lập luận rằng lớp trình bày trong bảng điều khiển của bạn có thể xử lý những ngày bị thiếu và thay vào đó chỉ hiển thị 0, nhưng một số công cụ (ví dụ: SSRS) sẽ không thể xử lý việc này.
Các ví dụ khác tôi đã thấy sử dụng các thủ thuật chuỗi thời gian tương tự (ngày / giờ +/- số) để thực hiện tất cả các loại tính toán cửa sổ. Nói chung, bất cứ khi nào trong một ngôn ngữ bắt buộc, bạn sẽ sử dụng một vòng lặp for với số lần lặp nổi tiếng, tính chất khai báo và thiết lập của SQL có thể sử dụng một mẹo dựa trên bảng số.
BTW, tôi cảm thấy cần phải gọi ra một thực tế rằng mặc dù sử dụng bảng số, nó cảm thấy giống như thực thi thủ tục bắt buộc, không rơi vào sai lầm khi cho rằng nó là bắt buộc. Để tôi lấy một ví dụ:
int x;
for (int i=0;i<1000000;++i)
x = i;
printf("%d",x);
Chương trình này sẽ xuất 999999, được đảm bảo khá nhiều.
Hãy thử tương tự trong SQL Server, sử dụng bảng số. Đầu tiên tạo bảng 1.000.000 số:
create table numbers (number int not null primary key);
go
declare @i int = 0
, @j int = 0;
set nocount on;
begin transaction
while @i < 1000
begin
set @j = 0;
while @j < 1000
begin
insert into numbers (number)
values (@j*1000+@i);
set @j += 1;
end
commit;
raiserror (N'Inserted %d*1000', 0, 0, @i)
begin transaction;
set @i += 1;
end
commit
go
Bây giờ, hãy thực hiện 'for loop':
declare @x int;
select @x = number
from numbers with(nolock);
select @x as [@x];
Kết quả là:
@x
-----------
88698
Nếu bây giờ bạn đang có một khoảnh khắc WTF (sau tất cả number
là khóa chính được nhóm!), Thủ thuật được gọi là quét thứ tự phân bổ và tôi đã không chèn @j*1000+@i
ngẫu nhiên ... Bạn cũng có thể mạo hiểm đoán và nói kết quả là vì song song và đó đôi khi có thể là câu trả lời chính xác.
Có rất nhiều troll dưới cây cầu này và tôi đã đề cập một số trong On SQL Server boolean điều hành ngắn mạch và T-SQL chức năng làm không bao hàm một trật tự nhất định thực hiện