2014-01-15 243 views
2

我正在嘗試爲特定的EmployeeID重新計算一些不同的數據列。計算運行總數

我希望hrs_YTD列保持運行總數。什麼是更新此信息的好方法?

HRS_YTD當前有0.00值。我不想在下表中獲得結果。

ID | CHEKDATE | CHEKNUMBR | HRS | HRS_YTD

EN344944 | 01/1/2014 | dd1001 | 40.00 | 40.00

EN344944 | 01/8/2014 | dd1002 | 30.00 | 70.00

EN344944 | 1/15/2014 | dd1003 | 32.50 | 102.50

等.....

DECLARE @k_external_id varchar(32) 

SET @k_external_id = 'EN344944' 

SELECT * INTO #tmpA 
FROM dbo.gp_check_hdr a 
WHERE a.EMPLOYID = @k_external_id 

SELECT a.ID, a.CHEKNMBR, a.CHEKDATE, 
     (SELECT CAST(SUM(a.[hours]) as decimal(18,2)) FROM #tmpA b 
     WHERE (b.CHEKDATE <= a.CHEKDATE and YEAR(b.CHEKDATE) = 2013)) AS hrs_ytd 
FROM #tmpA a 
WHERE YEAR(a.CHEKDATE) = 2013 

我真的不知道,如果我可以別名一個表像我#tmpA B均無,但它在過去爲我工作。這並不意味着它是一個很好的做事方式。有人能告訴我一種獲得我需要的結果的方法嗎?

回答

3

還沒有測試,但你可以試試這個

DECLARE @k_external_id varchar(32) 

SET @k_external_id = 'EN344944' 

SELECT g1.primarykey, g1.ID,g1.CHEKDATE, g1.CHEKNUMBR, g1.HRS ,(SELECT SUM(g2.HRS) 
        FROM dbo.gp_check_hdr g2 
        WHERE g2.ID = @k_external_id AND 
        (g2.primarykey <= g1.primarykey)) as HRS_YTD 
FROM dbo.gp_check_hdr g1 
WHERE g1.ID = @k_external_id 
ORDER BY g1.primarykey; 

http://www.codeproject.com/Articles/300785/Calculating-simple-running-totals-in-SQL-Server

+0

+1這很有效。感謝您的幫助和鏈接。 – HKImpact

1

我會做的方式是computed columnuser defined function的組合。

該函數允許彙總數據。在一個計算列中,你只能使用同一行的字段,因此調用一個函數(這是允許的)是必要的。

計算列允許它連續工作,不需要任何附加查詢或臨時表等。設置後,您不需要運行夜間更新或觸發器或任何類型的數據以更新數據,包括何時記錄更改或被刪除。

這裏是我的解決方案...和SqlFiddle:http://www.sqlfiddle.com/#!3/cd8d6/1/0

編輯: 我已經更新這反映您需要每名員工計算運行總計。 SqlFiddle也更新了。

功能:

Create Function udf_GetRunningTotals ( 
    @CheckDate DateTime, 
    @EmployeeID int 
) 
Returns Decimal(18,2) 
As 
Begin 
    Declare @Result Decimal(18,2) 
    Select @Result = Cast(Sum(rt.Hrs) As Decimal(18,2)) 
     From RunningTotals rt 
     Where rt.CheckDate <= @CheckDate 
      And Year(rt.CheckDate) = Year(@CheckDate) 
      And rt.EmployeeID = @EmployeeID 
    Return @Result 
End 

表模式:

Create Table [dbo].[RunningTotals](
    [ID] [int] Identity(1,1) NOT NULL, 
    [EmployeeID] [int] NOT NULL, 
    [CheckDate] [datetime] NOT NULL, 
    [CheckNumber] [int] NOT NULL, 
    [Hrs] [decimal](18, 2) NOT NULL, 
    [Hrs_Ytd] AS ([dbo].[udf_GetRunningTotals]([CheckDate],[EmployeeID])), -- must add after table creation and function creation due to inter-referencing of table and function 

    Constraint [PK_RunningTotals3] Primary Key Clustered (
     [ID] ASC 
    ) With (
     PAD_INDEX = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     IGNORE_DUP_KEY = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON 
    ) 
) On [PRIMARY] 

結果會從中總結出YTD小時,每一年。

注 -

因爲是因爲它們相互引用您不能創建函數或表。 首先,創建除了計算列以外的所有表格; 然後,創建該功能。 最後,修改表格並添加計算列。

這裏是一個完整的運行測試腳本:

-- Table schema 
Create Table [dbo].[RunningTotals](
    [ID] [int] Identity(1,1) NOT NULL, 
    [EmployeeID] [int] NOT NULL, 
    [CheckDate] [datetime] NOT NULL, 
    [CheckNumber] [int] NOT NULL, 
    [Hrs] [decimal](18, 2) NOT NULL, 

    Constraint [PK_RunningTotals3] Primary Key Clustered (
     [ID] ASC 
    ) With (
     PAD_INDEX = OFF, 
     STATISTICS_NORECOMPUTE = OFF, 
     IGNORE_DUP_KEY = OFF, 
     ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON 
    ) 
) On [PRIMARY] 
Go 

-- UDF Function to compute totals 
Create Function udf_GetRunningTotals ( 
    @CheckDate DateTime, 
    @EmployeeID int 
) 
Returns Decimal(18,2) 
As 
Begin 
    Declare @Result Decimal(18,2) 
    Select @Result = Cast(Sum(rt.Hrs) As Decimal(18,2)) 
     From RunningTotals rt 
     Where rt.CheckDate <= @CheckDate 
      And Year(rt.CheckDate) = Year(@CheckDate) 
      And rt.EmployeeID = @EmployeeID 
    Return @Result 
End 
Go 

-- Add the computed column to the table 
Alter Table RunningTotals Add [Hrs_Ytd] As (dbo.udf_GetRunningTotals(CheckDate, EmployeeID)) 
Go 

-- Insert some test data 
Insert into RunningTotals Values (334944, '1/1/2014', '1001', 40.00) 
Insert into RunningTotals Values (334944, '1/5/2014', '1002', 30.00) 
Insert into RunningTotals Values (334944, '1/15/2014', '1003', 32.50) 

Insert into RunningTotals Values (334945, '1/5/2014', '1001', 10.00) 
Insert into RunningTotals Values (334945, '1/6/2014', '1002', 20.00) 
Insert into RunningTotals Values (334945, '1/8/2014', '1003', 12.50) 


-- Test the computed column 
Select * From RunningTotals 
+0

非常感謝!這是一個很好的答案! – HKImpact

+0

@HKImpact酷我知道它有點不同,但應該完成你所需要的。我更新了我的答案,包括計算每位員工的運行總數。 –

0

你的子查詢應該只是罰款。

我用一個表變量來代替臨時表。

我還將temp表中插入的結果限制爲2013,以簡化最終的select語句,並將臨時表中的結果限制爲您所需的值。唯一的另一件事是使用ID將子查詢連接到主查詢,但是您應該使用的工作方式是將臨時表中的結果限制爲特定的ID。

DECLARE 
    @k_external_id varchar(32) 
    ,@k_reporting_year int 

SET @k_external_id = 'EN344944' 
SET @k_reporting_year = 2013 

DECLARE @temp TABLE(
    ID NVARCHAR(32) 
    ,CheckDate DATE 
    ,CheckNumber NVARCHAR(6) 
    ,HRS DECIMAL(18,2) 
) 

INSERT INTO @temp (
    ID 
    ,CheckDate 
    ,CheckNumber 
    ,HRS 
) 
    SELECT 
     ID 
     ,CHEKDATE 
     ,CHEKNMBR 
     ,[hours] 
    FROM 
     dbo.gp_check_hdr 
    WHERE 
      EMPLOYID = @k_external_id 
     AND YEAR(a.CHEKDATE) = @k_reporting_year 

SELECT 
    ID 
    ,CheckDate 
    ,CheckNumber 
    ,HRS 
    ,(SELECT SUM(HRS) FROM @temp b WHERE a.ID = b.ID AND b.CheckDate <= a.CheckDate) AS hrs_ytd 
FROM 
    @temp a