我正在尝试为特定的EmployeeID重新计算几个不同的数据列。
我希望hrs_YTD列保持运行总计。更新此信息的好方法是什么?
HRS_YTD目前有0.00值。我不想在下表中得到结果。
ID | CHEKDATE | CHEKNUMBR | HRS | HRS_YTD
EN344944 | 01/1/2014 | dd1001 | 40.00 | 40.00
EN344944 | 2014年1月8日| 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那样使用别名,但过去它对我有用。这并不意味着它是一种很好的做事方式。有人能告诉我一种方法来实现我需要的结果吗?
答案 0 :(得分: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
答案 1 :(得分:1)
我这样做的方式是computed column
和user 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]
结果将计算每年的年初至今。
注意 -
您不能按原样创建函数或表,因为它们相互引用。 首先,使用除计算列之外的所有列创建表; 然后,创建该功能。 最后,更改表并添加计算列。
这是一个完整运行的测试脚本:
-- 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
答案 2 :(得分:0)
你的子查询应该可以正常工作。
我使用表变量代替临时表。
我还将临时表中插入的结果限制为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