2010-09-20 74 views
8

Tôi có một thủ tục lưu trữ T-SQL, nơi tôi muốn tìm kiếm một giá trị cụ thể và giới hạn tìm kiếm theo ngày cụ thể nếu chúng được chuyển vào. được thông qua vào một trong những ngày này, sau đó tôi muốn bỏ qua những điều đó. Cách tôi đang suy nghĩ để làm điều này bằng cách thiết lập các ngày đầu vào tối thiểu hoặc tối đa nếu chúng là null. Tôi không muốn hardcode các giá trị tối thiểu và tối đa mặc dù. Vì vậy, tôi tự hỏi tương đương SQL của C# DateTime.MaxValueDateTime.MinValue là gì.SQL tìm kiếm ngày giữa các giá trị hoặc Min/Max nếu NULL

Tôi đang nghĩ đến việc sử dụng liên hiệp như vậy

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, <MinDateTime>) AND 
       Coalesce(@EndDate, <MaxDateTime>) 

Có một xây dựng trong chức năng/liên tục/biến/enum tôi có thể sử dụng cho các biến <MinDateTime><MaxDateTime>?

Mọi đề xuất?

Trả lời

11

Không có chức năng nào như vậy trong SQL Server. Bạn có thể dễ dàng tìm thấy số min and max dates được phép trong BOL (1753-01-01 - 9999-12-31). Hoặc bạn có thể khó viết mã một ngày khác một cách dễ dàng (nếu bạn thực sự làm việc với sinh nhật, 1800-01-01 - 2100-12-31 có lẽ sẽ đủ). Hoặc bạn có thể (nếu nó là truy vấn nhiều bạn đã thể hiện), có liên hiệp rơi trở lại vào ngày sinh nhật chính nó:

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, Birthday) AND 
       Coalesce(@EndDate, Birthday) 

Nhưng lưu ý rằng điều này sẽ không nhất thiết phải mở rộng quy mô cũng cho các bảng rất lớn.

Sửa sau khi chấp nhận, để đáp ứng với nhận xét từ OP

Nói chung, cho SQL, nếu bạn đang cần "tham khảo" dữ liệu thường xuyên, bạn thêm nó như là một bảng chính mình. (Google cho "bảng lịch" hoặc "số bảng sql"). Vì vậy, trong trường hợp này, nếu bạn muốn, bạn có thể thêm một "hằng số" (hoặc có thể "giới hạn" bảng):

create table Constants (
    Lock char(1) not null, 
    datetimeMin datetime not null, 
    datetimeMax datetime not null, 
    intMin int not null, 
    intMax int not null, 
    /* Other Min/Max columns, as required */ 
    constraint PK_Constants PRIMARY KEY (Lock), 
    constraint CK_Constants_Locked CHECK (Lock='X') 
) 
insert into Constants (Lock,datetimeMin,datetimeMax,intMin,intMax) 
select 'X','17530101','99991231',-2147483648,2147483647 

Mà bạn sau đó có thể tham khảo trong các truy vấn (hoặc thông qua một subselect, hoặc bằng cách xuyên tham gia vào bảng này). Ví dụ.

SELECT EmployeeName 
FROM Employee, Constants 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, Constants.datetimeMin) AND 
       Coalesce(@EndDate, Constants.datetimeMax) 

(Các Khóa, khóa chính, và Kiểm tra hạn chế, làm việc cùng nhau để đảm bảo rằng chỉ có một hàng duy nhất bao giờ sẽ tồn tại trong bảng này)

+0

Rất thú vị. Tôi chưa từng thấy kiểu mẫu Coalesce (@StartDate, Birthday) trước đây. Tôi nghĩ rằng việc tạo một biến được gọi là maxdate và mindate và thiết lập các giá trị của nó cho các ngày được mã hóa cứng có thể dễ đọc hơn nhiều. Nhưng yeah, thông tin chính tôi đang tìm kiếm là thiếu enums/hằng số trong SQL – Chaitanya

+0

Re COALESCE trick - +1 với tuyên bố rằng nó sẽ không mở rộng cho các bảng lớn, SQL Server dường như không thể sử dụng chỉ mục trên cột Sinh nhật. Mã hóa cứng tối thiểu và ngày tối đa hoạt động tốt với chỉ mục. –

3

Không có chức năng tích hợp để nhận được giá trị thời gian ngày tối thiểu hoặc tối đa. Bạn phải mã hóa cứng các giá trị hoặc lấy các giá trị từ cơ sở dữ liệu.

Nếu tham số là NULL bạn chỉ có thể chọn tối thiểu & ngày tối đa từ bảng Employee.

IF (@StartDate IS Null) 
BEGIN 
SELECT @StartDate = MIN(Birthday) FROM Employee 
END 


IF (@EndDate IS Null) 
BEGIN 
SELECT @EndDate = MAX(Birthday) FROM Employee 
END 

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN @StartDate AND @EndDate 
+1

Tôi không nghĩ rằng đây là những gì Chaitanya nghĩa. –

+0

+1 Nó có thể không chính xác những gì Chaitanya đã yêu cầu nhưng nó đáp ứng các yêu cầu đủ tốt. Không có hardcoding min và tối đa datetime cần thiết và cùng một truy vấn có thể được sử dụng cho các trường hợp null cũng như – InSane

4

Đối với SQL Server cụ thể, theo BOL, các giới hạn :

  • datetime: 1753/01/01 00:00:00 qua 9999-12-31 23: 59: 59,997
  • smalldatetime: 1900-01-01 00:00:00 qua 2079-06- 06 23: 59: 29.998
  • date: 0001-01-01 đến 9999-12-31
  • datetime2: 0001-01-01 00:00:00 đến 9999-12-31 23:59:59.9999999

Như bạn thấy, nó phụ thuộc vào loại dữ liệu chính xác của bạn.

Đối với các truy vấn, tôi sẽ làm điều đó như thế này:

SELECT EmployeeName 
FROM Employee 
WHERE EmployeeID = @EmployeeId 
AND (@StartDate IS NULL 
    OR Birthday >= @StartDate) 
AND (@EndDate IS NULL 
    OR Birthday <= @EndDate) 
+0

+1 để tham khảo. Đối với truy vấn - nó cần phải được kiểm tra, 'GIỮA ... COALESCE' có thể dễ hiểu hơn đối với người lập kế hoạch truy vấn. – Unreason

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