2012-03-21 17 views
1

給定一個包含員工狀態和生效日期的表格,如何才能檢索僅反映狀態變化的數據?查詢以反映數據中的實際重大變化

例如,給定的結構如下:

DECLARE @STATUSES TABLE(
    EMPLOYEE_ID INT NOT NULL, 
    EFFECTIVE_DATE DATE NOT NULL, 
    STATUS_CODE CHAR(1) NOT NULL 
) 
INSERT @STATUSES VALUES (1, '2012-01-01', 'A') 
INSERT @STATUSES VALUES (1, '2012-02-28', 'A') 
INSERT @STATUSES VALUES (1, '2012-03-01', 'T') 
INSERT @STATUSES VALUES (2, '2012-01-01', 'A') 
INSERT @STATUSES VALUES (2, '2012-02-14', 'A') 
INSERT @STATUSES VALUES (2, '2012-03-10', 'A') 
INSERT @STATUSES VALUES (3, '2012-02-01', 'A') 
INSERT @STATUSES VALUES (3, '2012-03-17', 'A') 
INSERT @STATUSES VALUES (3, '2012-03-18', 'T') 
INSERT @STATUSES VALUES (3, '2012-04-01', 'A') 
INSERT @STATUSES VALUES (4, '2012-03-01', 'A') 

什麼查詢可以用來導致以下?

EMPLOYEE_ID  EFFECTIVE_DATE  STATUS_CODE 
1    2012-01-01   A 
1    2012-03-01   T 
2    2012-01-01   A 
3    2012-02-01   A 
3    2012-03-18   T 
3    2012-04-01   A 
4    2012-03-01   A 

換句話說,我要離開了那些具有相同的員工ID和狀態代碼作爲其前一個,如果與之前的生效日期存在的記錄。請注意,員工1僅列出兩次,因爲狀態只有兩次實際更改 - 2012-02-28的狀態變化無關緊要,因爲狀態未從早期日期更改。另請注意,員工2僅列出一次,因爲儘管有三條記錄,他的狀態從未改變。只顯示每個更改的最早日期。

回答

1

隨着一些進一步的實驗,它看起來像這樣會做我想做的。

;WITH cte 
    AS (SELECT ROW_NUMBER() OVER (PARTITION BY EMPLOYEE_ID ORDER BY EFFECTIVE_DATE) AS rownum 
       ,EMPLOYEE_ID 
       ,EFFECTIVE_DATE 
       ,STATUS_CODE 
     FROM @STATUSES) 
SELECT t2.EMPLOYEE_ID 
     ,t2.EFFECTIVE_DATE 
     ,t2.STATUS_CODE 
FROM cte t2 
     LEFT JOIN cte t1 
     ON t2.EMPLOYEE_ID = t1.EMPLOYEE_ID 
      AND t2.STATUS_CODE = t1.STATUS_CODE 
      AND t2.rownum = t1.rownum + 1 
WHERE t1.EMPLOYEE_ID IS NULL 
+1

或者,你可以在'ON'子句中添加'AND t2.STATUS_CODE = t1.STATUS_CODE',並將'WHERE'子句修改爲'WHERE t1.EMPLOYEE_ID IS NULL'。 – 2012-03-21 13:53:00

+0

@AndriyM好點,我喜歡更好的方式,謝謝。更新。 – JustinStolle 2012-03-21 16:23:39

0
SELECT 
    EMPLOYEE_ID, MIN(EFFECTIVE_DATE) AS EFFECTIVE_DATE, STATUS_CODE 
FROM 
    (
    SELECT 
     T1.EMPLOYEE_ID, T1.EFFECTIVE_DATE, T1.STATUS_CODE, 
     MAX(T2.EFFECTIVE_DATE) AS MOST_RECENT_PREVIOUS_STATUS_DATE 
    FROM 
     @STATUSES T1 
     LEFT JOIN 
     @STATUSES T2 
     ON 
     T1.EMPLOYEE_ID = T2.EMPLOYEE_ID 
      AND 
     T1.EFFECTIVE_DATE > T2.EFFECTIVE_DATE 
      AND 
     T1.STATUS_CODE <> T2.STATUS_CODE 
    GROUP BY 
     T1.EMPLOYEE_ID, T1.EFFECTIVE_DATE, T1.STATUS_CODE 
    ) SubQuery 
GROUP BY 
    EMPLOYEE_ID, STATUS_CODE, MOST_RECENT_PREVIOUS_STATUS_DATE 
+0

這也適用。 – JustinStolle 2012-03-21 06:20:21

0

你可以使用光標

您將需要兩組變量:@PreviousRecord和@CurrentRecord

聲明光標表由僱員和日期排序

取從光標的第一條記錄到@PreviousRecord變量 - 取決於您的要求,將其註冊爲重大更改(將記錄寫入臨時表)

然後設置一個循環:
獲取下一個記錄到@CurrentRecord變量
與以前的記錄進行比較,如果它匹配了顯著改變您的要求將其寫入臨時表
移動@ CurrentRecord變量寫入@PreviousRecord變量

我很想知道CTE方法是否更高效

相關問題