2016-06-26 4 views
1

nehme ich eine Tabelle wie folgt aus:Wie Spaltennamen erhalten, die aktualisiert worden

Table 1: 
    date account name type status open_account_date 
    31.12.14 1000 20 40 50  31.12.14 
    2.1.15 1000 10 10 50  31.12.14 
    3.1.15 1000  5 15 50  31.12.14 

und ich möchte eine Übersichtstabelle, wie dies für das erste Quartal bauen:

account numOfChanges Changes 
1000  4   (name, type) 

der ersten Zeile in Tabelle 1 zeigt an, dass das Konto geöffnet wurde und jemand für den Account einige Details eingegeben hat, aber die anderen zeigen Änderungen an, aber ich möchte wissen, welche Felder geändert wurden. Gibt es einen Vorschlag oder eine Idee, wie man das macht?

Antwort

0
DECLARE @StartOfQuarter DATE = '1/1/2015' 

;WITH cteRcordStateBeforeQuarter AS (
    SELECT 
     [date] 
     ,account 
     ,name 
     ,[type] 
     ,[status] 
     ,open_account_date 
     ,RowNum = ROW_NUMBER() OVER (PARTITION BY account ORDER BY [date] DESC) 
    FROM 
     #Table 
    WHERE 
     [date] < @StartOfQuarter 
) 

, cteRecordStatesDuringQuarter AS (
    SELECT 
     [date] 
     ,account 
     ,name 
     ,[type] 
     ,[status] 
     ,open_account_date 
     ,RowNum = ROW_NUMBER() OVER (PARTITION BY account ORDER BY [date] ASC) + 1 
     --add 1 because the first row is going to be the last one prior to quarter 
     ,LatestChangeRowNum = ROW_NUMBER() OVER (PARTITION BY account ORDER BY [date] DESC) 
    FROM 
     #Table 
    WHERE 
     DATEPART(QQ,[date]) = 1 
     --change to suite ongoing needs such as quater and YEAR([date]) = ?? 
) 

, cteRecursive AS (
    SELECT 
     [date] 
     ,account 
     ,name 
     ,[type] 
     ,[status] 
     ,open_account_date 
     ,RowNum 
     ,LatestChangeRowNum = 0 
     ,NumOfChanges = 0 
     ,[Changes] = CAST('' AS VARCHAR(100)) 
    FROM 
     cteRcordStateBeforeQuarter 
    WHERE 
     RowNum = 1 

    UNION ALL 

    SELECT 
     q.[date] 
     ,q.account 
     ,q.name 
     ,q.[type] 
     ,q.[status] 
     ,q.open_account_date 
     ,q.RowNum 
     ,LatestChangeRowNum = CAST(q.LatestChangeRowNum AS INT) 
     ,NumOfChanges = r.NumOfChanges 
      + CASE WHEN ISNULL(q.name,-99999) <> ISNULL(r.name,-99999) THEN 1 ELSE 0 END 
      + CASE WHEN ISNULL(q.[type],-99999) <> ISNULL(r.[type],-99999) THEN 1 ELSE 0 END 
      + CASE WHEN ISNULL(q.[status],-99999) <> ISNULL(r.[status],-99999) THEN 1 ELSE 0 END 
      + CASE WHEN ISNULL(q.open_account_date,'1/1/1900') <> ISNULL(r.open_account_date,'1/1/1900') THEN 1 ELSE 0 END 
     ,[Changes] = CAST(ISNULL(r.[Changes],'') 
      + CASE WHEN ISNULL(q.name,-99999) <> ISNULL(r.name,-99999) AND r.[Changes] NOT LIKE '%name%' THEN ',name' ELSE '' END 
      + CASE WHEN ISNULL(q.[type],-99999) <> ISNULL(r.[type],-99999) AND r.[Changes] NOT LIKE '%type%' THEN ',type' ELSE '' END 
      + CASE WHEN ISNULL(q.[status],-99999) <> ISNULL(r.[status],-99999) AND r.[Changes] NOT LIKE '%status%' THEN ',status' ELSE '' END 
      + CASE WHEN ISNULL(q.open_account_date,'1/1/1900') <> ISNULL(r.open_account_date,'1/1/1900') AND r.[Changes] NOT LIKE '%open_account_date%' THEN ',open_account_date' ELSE '' END 
      AS VARCHAR(100)) 
    FROM 
     cteRecordStatesDuringQuarter q 
     INNER JOIN cteRecursive r 
     ON q.account = r.account 
     AND q.RowNum = r.RowNum + 1 
) 

SELECT 
    account 
    ,NumOfChanges 
    ,[Changes] = REPLACE(IIF(CHARINDEX(',',[Changes]) = 1, RIGHT([Changes],LEN([Changes]) - 1),[Changes]),',',', ') 
FROM 
    cteRecursive 
WHERE 
    LatestChangeRowNum = 1 

Wenn Sie, wo die Verwendung von SQL 2012 + wäre es ein wenig leichter sein, weil Sie LAG oder LEAD Fensterfunktionen und IIF statt Fall nutzen könnten. Aber eine rekursive CTE funktioniert auch ziemlich gut. Ich nehme an, dass Ihr Recordset mehrere Accounts sowie mehrere Quartale und dort für mehrere Recordstates vor dem Quartal haben wird. Aus diesem Grund müssen Sie die Datumslogik ein wenig anpassen, aber das wird Ihnen den Kern geben.

Zuerst den Datensatzstatus vor dem Quartal finden. Dann finden Sie alle Änderungen während des Quartals. Fügen Sie einige Zeilennummern hinzu, um zu bestimmen, welche die erste und welche die letzte Änderung ist. Verwenden Sie dann eine rekursive CTE, um auf Änderungen zu prüfen. Am Ende müssen Sie nur die Zeichenfolge formatieren, wie Sie möchten.