2009-05-28 26 views
7

Tôi đang viết chế độ xem cơ sở dữ liệu để tổng hợp một loạt bản ghi có giá trị trong cột ngày trong vòng 7 ngày qua. Nó trông giống như thế này:Làm cách nào để tránh sử dụng getdate() trong chế độ xem SQL?

CREATE VIEW RecentRecordSum AS 
SELECT  t.ID, 
      SUM(t.SomeValue) AS ValueSum 
FROM  SomeTable t 
WHERE  t.RecordDate >= DATEADD(d,-7,GETDATE()) 
GROUP BY t.ID 

Có cách nào để thực hiện điều này mà không cần GETDATE() trực tiếp trong mệnh đề where?

Tôi đang sử dụng SQL Server 2000 và 2005.

Nhìn vào kế hoạch truy vấn cho thấy rằng chi phí của getdate() gọi là chỉ có 0,03% của toàn bộ truy vấn (đó là đáng kể phức tạp hơn so với cái ở trên), vì vậy hiệu suất không phải là một vấn đề, tuy nhiên tôi thích các truy vấn của tôi là xác định.

Lý tưởng nhất là tôi cũng muốn hiển thị tham số -7 làm cột để có thể sử dụng nó trong mệnh đề where của một cái gì đó đang truy vấn chế độ xem. Hiện tại tôi đang dự tính một số lượt xem nhỏ cho các cửa sổ 7, 14, 28 ngày.

+0

Không chắc nếu tôi hiểu câu hỏi. Nó sẽ ở đâu nếu không ở trong mệnh đề where? Bạn đang nghĩ về một số loại tham số mà bạn vượt qua? – micahtan

+0

Tôi giả định điều này là để tránh hiệu suất hit đánh giá GETDATE() cho mỗi hàng duy nhất của resultset. – Joe

+0

Tại sao bạn cho rằng nó được đánh giá cho mỗi hàng? – RedFilter

Trả lời

6

Một lý do cho câu hỏi của bạn có thể là làm cho chế độ xem tối ưu hóa hơn bằng cách xóa chuyển đổi dữ liệu. không thể làm điều đó trong một cái nhìn, bạn sẽ cần phải làm cho nó một thủ tục lưu trữ và thực hiện chuyển đổi thành một biến:

CREATE PROCEDURE RecentRecordSum AS 

DECLARE @adate DATETIME 

SELECT @adate = DATEADD(d, -7, GETDATE()) 

SELECT  t.ID, 
      SUM(t.SomeValue) AS ValueSum 
FROM  SomeTable t 
WHERE  t.RecordDate >= @adate 
GROUP BY t.ID 
0
SELECT CURRENT_TIMESTAMP 

SELECT {fn NOW()} 

tôi có thể đã hiểu lầm câu hỏi, nếu bạn đang cố gắng để di chuyển getdate() và không thay thế nó, bạn có thể thực hiện việc đánh giá trong một Có khoản tức là

CREATE VIEW RecentRecordSum AS 
SELECT  t.ID, 
      SUM(t.SomeValue) AS ValueSum 
FROM  SomeTable t 
GROUP BY t.ID, t.RecordDate 
HAVING  t.RecordDate >= DATEADD(d,-7,GETDATE()) 
0

Nếu tôi hiểu chính xác câu hỏi, bạn luôn có thể thử tham gia bên trong bằng một bộ chứa GETDATE() như trong truy vấn sau:

SELECT  t.ID, 
      SUM(t.SomeValue) AS ValueSum 
FROM  SomeTable t 
INNER JOIN (SELECT DATEADD(d,-7,GETDATE()) AS MIN_DATE) MIN_DATE_SET 
ON t.RecordDate >= MIN_DATE_SET.MIN_DATE 
GROUP BY t.ID 

EDIT: Tôi đã xem xét một kế hoạch truy vấn cho một kịch bản tương tự, và chúng giống nhau. YMMV.

2

bắn Một trong bóng tối, như bao người khác ...

Có lẽ bạn đang muốn làm cho một khung nhìn được lập chỉ mục này, cái mà bạn sẽ không thể làm với getdate(), vì nó là một hàm không xác định. Tôi đã phá vỡ này trong quá khứ bằng cách gọi getdate() từ bên trong một quan điểm cho rằng chỉ chứa

select getdate() 

Mức độ gián tiếp là đủ để đánh lừa SQL Server 2000 và cho phép tôi sử dụng schemabinding, nhưng tôi không thể đảm bảo này sẽ hoạt động với các phiên bản sau.

+0

Tôi sẽ kiểm tra điều này - cảm ơn – geofftnz

+0

Đã cố gắng thực hiện điều này trong năm 2008. Không hoạt động, không may là 'Msg 4513, Cấp 16, Tiểu bang 2, Thủ tục view_ProductSearch, Dòng 5 [Dòng bắt đầu Batch 9] Không thể xem lược đồ ràng buộc' dbo .view_ProductSearch '. 'dbo.view_CurrentDate' không phải là lược đồ bị ràng buộc.' –

+0

Không phải là tôi đề nghị điều này, nhưng bạn có thể tạo một hàm CLR trả về ngày hiện tại và đánh dấu nó là IsDeterministic. – RedFilter

0

Giả sử bạn có dữ liệu trong đó cho ngày gần đây nhất, một subquery có lẽ có thể làm việc:

CREATE VIEW RecentRecordSum AS 
SELECT  t.ID, 
      SUM(t.SomeValue) AS ValueSum 
FROM  SomeTable t 
WHERE  t.RecordDate >= DATEADD(d,-7,(Select Max(RecordDate) From SomeTable)) 
GROUP BY t.ID 
Các vấn đề liên quan