2015-05-31 15 views
5

Dưới đây là một số mã SQL Server mà tôi đã làm việc. Bây giờ tôi biết rằng việc sử dụng con trỏ là một ý tưởng tồi nói chung, nhưng tôi không thể tìm ra cách khác để tôi có thể thực hiện công việc này. Hiệu suất là khủng khiếp với con trỏ. Tôi thực sự chỉ sử dụng một số câu lệnh IF đơn giản với một vòng lặp, nhưng không thể dịch nó thành SQL. Tôi đang sử dụng SQL Server 2012.Vòng lặp trong SQL Server không có con trỏ

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 

Về cơ bản, làm cách nào để giữ @counter này không có con trỏ. Tôi cảm thấy như giải pháp rất đơn giản, nhưng tôi đã đánh mất bản thân mình. Cảm ơn bạn đã tìm kiếm.

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 @[email protected] 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 @[email protected]+1; 
     set @[email protected]; 
     set @[email protected]+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 @[email protected]+1; 
      set @[email protected]; 
      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 @[email protected]+1; 
     end 
    fetch next from curr into @EmployeeID, @SequenceNum, @action; 
    end 

close curr; 
deallocate curr; 

Dưới đây là mã để tạo bảng mẫu. Tôi muốn tăng EMPRECORD mỗi khi bản ghi là '1-HR', nhưng đặt lại cho mỗi NGƯỜI LÀM VIỆC mới. Trước khi mã này được thực hiện, EMPRECORD là null cho tất cả các bản ghi. Bảng này cho thấy kết quả mục tiêu.

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] 
+0

@ala Cảm ơn. Tôi đã thêm một bảng đầu ra mẫu. – bheltzel

Trả lời

5

này nên tái tạo logic của con trỏ một cách hiệu quả hơn

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; 
+0

Ohhhh Tôi thấy bây giờ. Bạn đúng. – Stephan

0

Để thực hiện "pseudo-con trỏ" chỉ sử dụng SQL tinh khiết, bạn có thể tạo một tự tham gia (ví dụ như trái bên ngoài tham gia) để cùng một bảng và cho mỗi hàng trong bảng bên trái chỉ định các hoạt động tương ứng để được thực hiện trên bảng bên phải. Hy vọng điều này có thể giúp đỡ. Trân trọng,

2

Bạn không chỉ ra phiên bản TSQL nào - giải pháp này áp dụng cho SQL 2008 chuyển tiếp.

Dựa trên con trỏ của bạn, tôi đoán tại các truy vấn sẽ là:

WITH worker1hr as (select WORKER, SEQUENCE FROM [DBO].[Transactional History] WHERE Action = '1-HR') 
, workerStart as (select WORKER, min(SEQUENCE) as StartSeq FROM [DBO].[Transactional History] group by worker) 
SELECT th.WORKER, SEQUENCE, ACTION 
, EMPRECORD 
, 1 + (select count(*) from worker1hr wh WHERE wh.WORKER = th.WORKER and wh.SEQUENCE <= th.SEQUENCE 
      AND WH.SEQUENCE > ws.StartSeq ) as QryEmpRecord 
    FROM [DBO].[Transactional History] th 
JOIN workerStart ws ON ws.WORKER = th.WORKER 
ORDER BY WORKER ,SEQUENCE 

LƯU Ý: các truy vấn TSQL mệnh đề WITH đòi hỏi một dấu chấm phẩy tiến hành nó. Lạ, nhưng là sự thật ....

Sản lượng:

enter image description here

+1

Cảm ơn bạn đã tìm kiếm. Tôi nghĩ rằng bạn có thể là một cái gì đó, nhưng điều này không chính xác những gì tôi đang cố gắng để thực hiện. Tôi đã đề cập trong một bình luận ở trên, đây là đầu ra thực sự chúng ta muốn (nơi EMPRECORD là những gì bạn đang gọi WorkerSeq): muốn lặp qua bảng theo thứ tự của SEQUENCE. Mỗi lần NHÂN VIÊN có hồ sơ '1-HR', chúng tôi tăng EMPRECORD. Đối với WORKER 1, 1-HR đầu tiên của anh ấy có EMPRECORD = 1, 1-HR thứ hai của anh ấy có EMPRECORD = 2, v.v. Khi chúng tôi đến Worker 2, reset reset và EMPRECORD được thiết lập trở lại 1. – bheltzel

+0

Tôi đã trả lời trong khi bạn gửi dữ liệu mẫu - Nhờ làm rõ, tôi đã cập nhật giải pháp. ROW_NUMBER() không còn được sử dụng nữa. – Stan

5

Tôi nghĩ rằng những gì bạn cần là một chức năng Windows với một tuyên bố trường hợp. Điều này đơn giản hơn và nên thực hiện tốt hơn tốt hơn con trỏ của bạn, đặc biệt nếu bạn có chỉ mục tốt.

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 

Kết quả (mỏ phù hợp với bạn):

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 
Các vấn đề liên quan