我正在重新訪問我爲報表編寫的一些舊代碼,當時我對SQL(MSSQL)還很陌生。它做它應該做的,但它不是最漂亮或最有效的。我怎樣才能重寫這個select語句使用組而不是使用循環
下面的虛擬代碼模仿了我現在所擁有的東西。在這裏,我試圖計算過去5周內開放的合約數量。對於這個例子,如果合同的開始日期發生在給定週期之前,並且結束日期發生在給定週期間或之後,合同就被認爲是開放的。
dbo.GetWeekStart(@date DATETIME,@NumOfWeeks INT,@FirstDayOfWeek CHAR(3))是將返回基於提供一種用於周指定數量的時間每週的第一天的功能。即SELECT * FROM dbo.GetWeekStart('20120719',-2,'MON')將於2012年7月19日之前返回2個星期一。
我該如何簡化?我認爲有人沒有循環就能做到這一點,但我一直無法弄清楚。
DECLARE @RunDate DATETIME,
@Index INT,
@RowCount INT,
@WeekStart DATETIME,
@WeekEnd DATETIME
DECLARE @Weeks TABLE
(
WeekNum INT IDENTITY(0,1),
WeekStart DATETIME,
WeekEnd DATETIME
)
DECLARE @Output TABLE
(
WeekStart DATETIME,
OpenContractCount INT
)
SET @RunDate = GETDATE()
INSERT INTO @Weeks (WeekStart, WeekEnd)
SELECT WeekStart,
DATEADD(ss,-1,DATEADD(ww,1,WeekStart))
FROM dbo.[GetWeekStart](@RunDate, -5, 'MON')
SET @RowCount = (SELECT COUNT(*) FROM @Weeks)
SET @Index = 0
WHILE @Index < @RowCount
BEGIN
SET @WeekStart = (SELECT WeekStart FROM @Weeks WHERE WeekNum = @Idx)
SET @WeekEnd = (SELECT WeekEnd FROM @Weeks WHERE WeekNum = @Idx)
INSERT INTO @Output (WeekStart, OpenContractCount)
SELECT @WeekStart,
COUNT(*)
FROM Contracts c
WHERE c.StartDate <= @WeekEnd
AND ISNULL(c.EndDate, GETDATE()) >= @WeekStart
SET @Index = @Index + 1
END
SELECT * FROM @Output
我花了一點時間回到這裏,但是這個解決方案對我來說效果很好,並且提供了比我原來的解決方案更高的性能。 – Curtis 2012-07-27 18:16:00