2012-04-17 96 views
1

稍微難以解釋,我的SQL Server不是最好的,但任何事情都可以在這裏完成。當前記錄和下一條記錄之間的列總和

首先,創建一些表:

CREATE TABLE [dbo].[Quarterly](
[QuarterDate] [datetime] NOT NULL, 
[SomeText] [nvarchar](50) NULL, 
CONSTRAINT [PK_Quarterly] PRIMARY KEY CLUSTERED 
(
[QuarterDate] ASC 
) 
GO 

CREATE TABLE [dbo].[TmpDegreeDays](
[Date] [datetime] NOT NULL, 
[Value] [nvarchar](50) NOT NULL, 
CONSTRAINT [PK_TmpDegreeDays] PRIMARY KEY CLUSTERED 
(
[Date] ASC 
) 
GO 

然後插入一些數據:

INSERT [dbo].[Quarterly] ([QuarterDate], [SomeText]) VALUES (CAST(0x00009CF100000000 AS DateTime), N'Blah') 
INSERT [dbo].[Quarterly] ([QuarterDate], [SomeText]) VALUES (CAST(0x00009D4B00000000 AS DateTime), N'Fools') 
INSERT [dbo].[Quarterly] ([QuarterDate], [SomeText]) VALUES (CAST(0x00009DA600000000 AS DateTime), N'Later') 
INSERT [dbo].[Quarterly] ([QuarterDate], [SomeText]) VALUES (CAST(0x00009E0400000000 AS DateTime), N'Something') 
INSERT [dbo].[Quarterly] ([QuarterDate], [SomeText]) VALUES (CAST(0x00009E5E00000000 AS DateTime), N'New year') 
INSERT [dbo].[Quarterly] ([QuarterDate], [SomeText]) VALUES (CAST(0x00009EC300000000 AS DateTime), N'In april') 

然後從2010-01-01插入日期範圍至(含)2012-03-10成表TmpDegreeDays

最後:

我想計算對於當前QuarterDateQuarterly結果集中下一條記錄之間的Quarterly表中的每條記錄,請使用[值]的和SUM。

喜歡的東西:最終輸出的

DECLARE @startDate datetime, @endDate datetime 
SET @startDate = '2010-01-01' 
SET @endDate = '2010-12-31' 

SELECT q.QuarterDate, q.SomeText, CustomSum = 
(SELECT SUM(CAST([Value] AS float)) 
FROM TmpDegreeDays 
WHERE [date] >= q.QuarterDate AND *Current QuarterDate* < *Some query here to get next row QuarterDate*) 

FROM Quarterly q 

WHERE q.QuarterDate BETWEEN @startDate AND @endDate 

例子我要找:

2010-01-01 Sum of [Value] between 2010-01-01 and 2010-03-31 
2010-04-01 Sum of [Value] between 2010-04-01 and 2010-06-30 
2010-07-01 Sum of [Value] between 2010-07-01 and 2010-09-31 
2010-10-03 Sum of [Value] between 2010-10-03 and 2010-10-03 

這是否有道理?

+1

首先:爲什麼你讓你的INSERT如此複雜?爲什麼不使用'INSERT INTO [dbo]。[Quarterly]([QuarterDate],[SomeText])VALUES('20100101',N'Blah')'等等? **很多**比你的奇怪的鑄造更容易.....另外:如果你有一個度數值的表 - **爲什麼**是'值'列'VARCHAR(50)'?不應該像'DECIMAL(10,4)'或類似的東西? Varchar在這裏完全沒有意義..... – 2012-04-17 21:08:15

+0

馬克 - 它不是我的代碼:-)我只是把它。相信我,它會做得更好 – 2012-04-17 21:17:35

+0

但是'SUM'甚至不會**在'VARCHAR'列工作** - 你一定要改變一些東西..... – 2012-04-17 21:18:34

回答

1

你可以嘗試這樣的事情 - 一個使用CTE(可在SQL Server 及更高版本)發現的日期每個季度,然後總結度值:

;WITH QuarterlyDates AS 
(  
    SELECT 
     QuarterDate, 
     QuarterEndDate = DATEADD(MILLISECOND, -3, DATEADD(MONTH, 3, QuarterDate)) 
    FROM [dbo].[Quarterly] 
) 
SELECT 
    qd.QuarterDate, qd.QuarterEndDate, 
    DegreeSum = (SELECT SUM(DegreeValue) 
       FROM [dbo].[TmpDegreeDays] 
       WHERE [Date] BETWEEN qd.QuarterDate AND qd.QuarterEndDate) 
FROM 
    QuarterlyDates qd 

奇怪功能確定QuarterEndDate的根源在於SQL Server中的DATETIME的精度爲3.33ms。因此,給定月份的最後日期是該月份的最後一天,時間爲23:59:59.997(不是.999)。因此,我需要在本季度的開始日期前增加三個月,然後從下一季度的開始日期減去3毫秒以獲取本季度的最後一個毫秒。確定,爲了從表格中得到一個季度的開始和結束日期,需要兩個嵌套的CTE以確定「下一個季度的結束日期減去3毫秒」本季度 - 這樣的事情:

;WITH QuarterStarts AS 
(
    SELECT 
     QuarterDate, 
     QNumber = ROW_NUMBER() OVER(ORDER BY QuarterDate) -- ordering number 
    FROM [dbo].[Quarterly] 
), 
Quarters AS 
(
    SELECT 
     QuarterStartDate = q1.QuarterDate, 
     QuarterEndDate = DATEADD(MILLISECOND, -3, q2.QuarterDate) 
    FROM 
     QuarterStarts q1 
    INNER JOIN 
     QuarterStarts q2 ON q2.QNumber = q1.QNumber + 1 
) 
SELECT 
    q.QuarterDate, q.QuarterEndDate, 
    DegreeSum = (SELECT SUM(DegreeValue) 
       FROM [dbo].[TmpDegreeDays] 
       WHERE [Date] BETWEEN q.QuarterDate AND q.QuarterEndDate) 
FROM 
    Quarters q 
+0

馬克 - 太棒了!我覺得這就是。但是有一個問題 - CTE需要放在最終結果集的Column中(仍然只能從QuarterDates表中選擇),這在原來的PROC中已經很遠了,我已經在這裏簡化並簡化了。有一些自定義列正在被創建,以便在最終結果集中返回(比如一些計算)。那麼我怎麼能在SPROC中進一步引用CTE呢? – 2012-04-17 21:22:46

+0

馬克 - 幾乎在那裏。我遇到的問題是QuarterDate和您添加的3個月。我需要刪除這個消息,因爲每個「客戶」都有自己的季度定義(從calander表中)。我需要從下一行數據中獲取下一個QuarterDate,並將其用作「結束」。有任何想法嗎? – 2012-04-17 22:00:22

+0

@Ahmedilyas:用一種方法來更新我的迴應,通過查看下一個的開始日期來確定當前季度的結束日期。 – 2012-04-18 05:14:39