bhe*_*zel 5 sql t-sql sql-server sql-server-2012
下面是我一直在研究的一些SQL Server代码.我现在知道使用光标通常是一个坏主意,但我无法弄清楚我还能做些什么.光标的性能很糟糕.我真的只是使用一些简单的IF语句逻辑与循环,但不能将其转换为SQL.我正在使用SQL Server 2012.
IF [Last Employee] = [Employee] AND [Action] = '1-HR'
SET [Employee Record] = @counter + 1
ELSE IF [Last Employee] != [Employee] OR [Last Employee] IS NULL
SET [Employee Record] = 1
ELSE
SET [Employee Record] = @counter
Run Code Online (Sandbox Code Playgroud)
基本上,如何在没有光标的情况下保持这个@counter.我觉得解决方案很简单,但我迷失了自己.谢谢你的期待.
declare curr cursor for
select WORKER, SEQUENCE, ACTION
FROM [DB].[Transactional History]
order by WORKER ,SEQUENCE asc
declare @EmployeeID as nvarchar(max);
declare @SequenceNum as nvarchar(max);
declare @LastEEID as nvarchar(max);
declare @action as nvarchar(max);
declare @currentEmpRecord int
declare @counter int;
open curr
fetch next from curr into @EmployeeID, @SequenceNum, @action;
while @@FETCH_STATUS=0
begin
if @LastEEID=@EmployeeID and @action='1-HR'
begin
set @sql = concat('update [DB].[Transactional History]
set EMPRECORD=',+ @currentEmpRecord, '+1
where WORKER=', @EmployeeID, ' and SEQUENCE=', @SequenceNum)
EXECUTE sp_executesql @sql
set @counter=@counter+1;
set @LastEEID=@EmployeeID;
set @currentEmpRecord=@currentEmpRecord+1;
end
else if @LastEEID is null or @LastEEID<>@EmployeeID
begin
set @sql = concat('update [DB].[Transactional History]
set EMPRECORD=1
where WORKER=', @EmployeeID, ' and SEQUENCE=', @SequenceNum)
EXECUTE sp_executesql @sql
set @counter=@counter+1;
set @LastEEID=@EmployeeID;
set @currentEmpRecord=1
end
else
begin
set @sql = concat('update [DB].[Transactional History]
set EMPRECORD=', @currentEmpRecord, '
where WORKER=', @EmployeeID, ' and SEQUENCE=', @SequenceNum)
EXECUTE sp_executesql @sql
set @counter=@counter+1;
end
fetch next from curr into @EmployeeID, @SequenceNum, @action;
end
close curr;
deallocate curr;
Run Code Online (Sandbox Code Playgroud)
下面是构建示例表的代码.我想在每次记录为'1-HR'时增加EMPRECORD,但是为每个新的WORKER重置它.在执行此代码之前,EMPRECORD对所有记录都为null.此表显示目标输出.
CREATE TABLE [DB].[Transactional History-test](
[WORKER] [nvarchar](255) NULL,
[SOURCE] [nvarchar](50) NULL,
[TAB] [nvarchar](25) NULL,
[EFFECTIVE_DATE] [date] NULL,
[ACTION] [nvarchar](5) NULL,
[SEQUENCE] [numeric](26, 0) NULL,
[EMPRECORD] [numeric](26, 0) NULL,
[MANAGER] [nvarchar](255) NULL,
[PAYRATE] [nvarchar](20) NULL,
[SALARY_PLAN] [nvarchar](1) NULL,
[HOURLY_PLAN] [nvarchar](1) NULL,
[LAST_MANAGER] [nvarchar](255) NULL
) ON [PRIMARY]
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'EMP-Position Mgt', CAST(N'2004-01-01' AS Date), N'1-HR', CAST(1 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), N'3', N'Hourly', NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'Change Job', CAST(N'2004-05-01' AS Date), N'5-JC', CAST(2 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), N'4', NULL, NULL, NULL, N'3')
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'EMP-Terminations', CAST(N'2005-01-01' AS Date), N'6-TR', CAST(3 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), N'4', NULL, NULL, NULL, N'4')
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'Change Job', CAST(N'2010-05-01' AS Date), N'5-JC', CAST(4 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), N'3', NULL, NULL, NULL, N'4')
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'EMP-Position Mgt', CAST(N'2011-05-01' AS Date), N'1-HR', CAST(5 AS Numeric(26, 0)), CAST(2 AS Numeric(26, 0)), N'3', N'Hourly', NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'CWR-Position Mgt', CAST(N'2012-01-01' AS Date), N'1-HR', CAST(6 AS Numeric(26, 0)), CAST(3 AS Numeric(26, 0)), NULL, NULL, NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'Organizations', CAST(N'2015-01-01' AS Date), N'3-ORG', CAST(7 AS Numeric(26, 0)), CAST(3 AS Numeric(26, 0)), NULL, NULL, NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'1', NULL, N'Organizations', CAST(N'2015-01-01' AS Date), N'3-ORG', CAST(8 AS Numeric(26, 0)), CAST(3 AS Numeric(26, 0)), NULL, NULL, NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'2', NULL, N'EMP-Terminations', CAST(N'2001-01-01' AS Date), N'6-TR', CAST(9 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), NULL, NULL, NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'2', NULL, N'EMP-Terminations', CAST(N'2001-05-01' AS Date), N'6-TR', CAST(10 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), NULL, NULL, NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'2', NULL, N'Change Job', CAST(N'2004-01-01' AS Date), N'5-JC', CAST(11 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), N'3', NULL, NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'2', NULL, N'Change Job', CAST(N'2004-01-01' AS Date), N'5-JC', CAST(12 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), N'3', NULL, NULL, NULL, N'3')
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'2', NULL, N'EMP-Position Mgt', CAST(N'2014-01-01' AS Date), N'1-HR', CAST(13 AS Numeric(26, 0)), CAST(2 AS Numeric(26, 0)), N'4', N'Salary', NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'3', NULL, N'EMP-Terminations', CAST(N'2012-01-01' AS Date), N'6-TR', CAST(14 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), NULL, NULL, NULL, NULL, NULL)
GO
INSERT [DB].[Transactional History-test] ([WORKER], [SOURCE], [TAB], [EFFECTIVE_DATE], [ACTION], [SEQUENCE], [EMPRECORD], [MANAGER], [PAYRATE], [SALARY_PLAN], [HOURLY_PLAN], [LAST_MANAGER]) VALUES (N'4', NULL, N'EMP-Position Mgt', CAST(N'2012-01-01' AS Date), N'1-HR', CAST(15 AS Numeric(26, 0)), CAST(1 AS Numeric(26, 0)), NULL, NULL, NULL, NULL, NULL)
GO
select * from DB.[Transactional History-test]
Run Code Online (Sandbox Code Playgroud)
这应该以更有效的方式重现光标的逻辑
WITH T
AS (SELECT *,
IIF(FIRST_VALUE([ACTION]) OVER (PARTITION BY WORKER
ORDER BY [SEQUENCE]
ROWS UNBOUNDED PRECEDING) = '1-HR', 0, 1) +
COUNT(CASE
WHEN [ACTION] = '1-HR'
THEN 1
END) OVER (PARTITION BY WORKER
ORDER BY [SEQUENCE]
ROWS UNBOUNDED PRECEDING) AS _EMPRECORD
FROM DB.[Transactional History-test])
UPDATE T
SET EMPRECORD = _EMPRECORD;
Run Code Online (Sandbox Code Playgroud)
我认为你需要的是带有case语句的Windows函数.这是简单,应该执行显著,特别是如果你有良好的指标比你更好的光标.
WITH CTE
AS
(
SELECT *,
CASE WHEN [action] = '1-HR' OR [Sequence] = MIN([sequence]) OVER (PARTITION BY worker)
THEN 1 --cnter increases by 1 whether the action is 1-HR OR the sequence is the first for that worker
ELSE 0 END cnter
FROM [Transactional History-test]
)
SELECT empRecord, --can add any columns you want here
SUM(cnter) OVER (PARTITION BY worker ORDER BY [SEQUENCE]) AS new_EMPRECORD --just a cumalative sum of cnter per worker
FROM CTE
Run Code Online (Sandbox Code Playgroud)
结果(我的匹配你的):
empRecord new_EMPRECORD
--------------------------------------- -------------
1 1
1 1
1 1
1 1
2 2
3 3
3 3
3 3
1 1
1 1
1 1
1 1
2 2
1 1
1 1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1196 次 |
| 最近记录: |