SQL Server查询以查看每月更改的内容

时间:2014-01-30 21:23:01

标签: sql-server

我正在努力开发一个查询来比较单个表中每月的变化,示例数据 -

+-----------------------------------------------------------+    
| TaxGroupDetails                                           |
+-----------+--+----------+--+-----------+--+---------------+  
| Tax Group |  | Tax Type |  |  Geocode  |  | EffectiveDate |  
+-----------+--+----------+--+-----------+--+---------------+  
|      2001 |  | 1D       |  | 440011111 |  |       1120531 |  
|      2001 |  | X1       |  | 440011111 |  |       1120531 |  
|      2001 |  | D3       |  | 440011111 |  |       1120531 |  
|      2001 |  | DGH      |  | 440011111 |  |       1120531 |  
|      2001 |  | 1D       |  | 440011111 |  |       1130101 |  
|      2001 |  | X1       |  | 440011111 |  |       1130101 |  
|      2001 |  | D3       |  | 440011111 |  |       1130101 |  
|      2001 |  | 1D       |  | 440011111 |  |       1140201 |  
|      2001 |  | X1       |  | 440011111 |  |       1140201 |  
|      2001 |  | D3       |  | 440011111 |  |       1140201 |  
|      2001 |  | Z9       |  | 440011111 |  |       1140201 |  
+-----------+--+----------+--+-----------+--+---------------+  

我希望看到表格中的变化,在税收组中添加或删除的内容,在前两个生效日期之间。

如果我在今年2月(1140201)运行查询,我试图根据样本数据获得的结果将是Z9(已添加)。

如果我在去年1月(1130101)运行查询,我希望看到DGH(已删除)

我希望有两个单独的查询,一个用于显示添加的内容,另一个用于显示已删除的内容。

我尝试了多种途径来提出这两个问题,但似乎无法获得正确的结果。谁能指出我正确的方向?

5 个答案:

答案 0 :(得分:0)

  SELECT
        Current.TaxGroup,
        Current.TaxType,
        Current.GeoCode,
        'Added'
  FROM
        TaxGroupDetails AS Current
  WHERE
        Current.EffectiveDate = @CurrentPeriod AND
        NOT EXISTS
        (
           SELECT *
           FROM TaxGroupDetails As Previous
           WHERE 
                 Previous.EffectiveDate = @PreviousPeriod
                 Current.TaxGroup = Previous.TaxGroup and
                 Current.TaxType = Previous.TaxType and 
                 Current.GeoCode = Previous.GeoCode
        )

  UNION ALL

  SELECT
        Current.TaxGroup,
        Current.TaxType,
        Current.GeoCode,
        'Added'
  FROM
        TaxGroupDetails AS Previous
  WHERE
        Previous.EffectiveDate = @PreviousPeriod AND

        NOT EXISTS
        (
           SELECT *
           FROM TaxGroupDetails As Current
           WHERE 
                 Current.EffectiveDate = @CurrentPeriod
                 Current.TaxGroup = Previous.TaxGroup and
                 Current.TaxType = Previous.TaxType and 
                 Current.GeoCode = Previous.GeoCode
        )

答案 1 :(得分:0)

基于集合的解决方案:将整个表格和整个表格之间的差异与所有日期向前推进一个时间间隔。这将消除除“new”代码之外的所有行。

SELECT
  [TaxGroup],
  [Tax Type],
  [EffectiveDate] 
FROM TaxGroupDetails t
EXCEPT
SELECT
  [TaxGroup],
  [Tax Type],
  ( SELECT MIN([EffectiveDate])
    FROM TaxGroupDetails
    WHERE [EffectiveDate] > t.[EffectiveDate]
      AND [TaxGroup] = t.[TaxGroup]
  )
FROM TaxGroupDetails t

要查看删除的内容,请改为向后投影。将子查询更改为:

    SELECT MAX([EffectiveDate])
    FROM TaxGroupDetails
    WHERE [EffectiveDate] < t.[EffectiveDate]
      AND [TaxGroup] = t.[TaxGroup]

答案 2 :(得分:0)

正如您所说,您需要两个查询,一个用于选择要比较的两组数据。

SELECT [Tax Group], [Tax Type], [Geocode], [EffectiveDate] 
FROM TaxGroupDetails 
WHERE EffectiveDate = 1120531 

SELECT [Tax Group], [Tax Type], [Geocode], [EffectiveDate] 
FROM TaxGroupDetails 
WHERE EffectiveDate = 1140201 

然后你需要使用某种形式的密钥将这两者结合在一起,税组和税收类型的组合在这里似乎是明智的。

SELECT *
FROM
(
    SELECT [Tax Group], [Tax Type], [Geocode], [EffectiveDate] 
    FROM TaxGroupDetails 
    WHERE EffectiveDate = 1120531 
) AS FirstGroup

FULL OUTER JOIN    

(
    SELECT [Tax Group], [Tax Type], [Geocode], [EffectiveDate] 
    FROM TaxGroupDetails 
    WHERE EffectiveDate = 1140201 
) AS SecondGroup

ON FirstGroup.[Tax Group] = SecondGroup.[Tax Group] 
AND FirstGroup.[Tax Type] = SecondGroup.[Tax Type] 

此处的FULL OUTER JOIN告诉SQL在另一行不存在时包含剩余的行。

最后让我们整理并订购列,而不是使用*:

SELECT COALESCE(FirstGroup.[Tax Group], SecondGroup.[Tax Group]), 
    COALESCE(FirstGroup.[Tax Type], SecondGroup.[Tax Type]),
    FirstGroup.Geocode, SecondGroup.Geocode,
    FirstGroup.EffectiveDate, SecondGroup.EffectiveDate
FROM
.
.
.

COALESCE从第一个匹配的列中删除NULL,因为我们说这些muct相等,所以没有任何一点显示这两个副本。

答案 3 :(得分:0)

如果你有SQL2012:

WITH t AS (
  SELECT *,
  ROW_NUMBER() OVER(PARTITION BY [TaxGroup], [Tax Type] ORDER BY [EffectiveDate] ASC) rownum
  FROM [TaxGroup]
)
SELECT *
FROM t
WHERE rownum = 1
  AND [EffectiveDate] = @Date

要获取其他查询,请将ASC更改为DESC

答案 4 :(得分:0)

试试这个/你可以从这个[部分]解决方案开始:

DECLARE @MyTable TABLE (
    ID INT IDENTITY PRIMARY KEY,
    [Tax Group] SMALLINT NOT NULL,
    [Tax Type] VARCHAR(3) NOT NULL,
    [Geocode] INT NOT NULL,
    [EffectiveDate] INT NOT NULL
);

INSERT @MyTable
          SELECT 2001, '1D ', 440011111, 1120531
UNION ALL SELECT 2001, 'X1 ', 440011111, 1120531
UNION ALL SELECT 2001, 'D3 ', 440011111, 1120531
UNION ALL SELECT 2001, 'DGH', 440011111, 1120531
UNION ALL SELECT 2001, '1D ', 440011111, 1130101
UNION ALL SELECT 2001, 'X1 ', 440011111, 1130101
UNION ALL SELECT 2001, 'D3 ', 440011111, 1130101
UNION ALL SELECT 2001, '1D ', 440011111, 1140201
UNION ALL SELECT 2001, 'X1 ', 440011111, 1140201
UNION ALL SELECT 2001, 'D3 ', 440011111, 1140201
UNION ALL SELECT 2001, 'Z9 ', 440011111, 1140201;

DECLARE @Results TABLE (
    ID INT NOT NULL,
    Rnk INT NOT NULL,
    EffectiveYear SMALLINT NOT NULL,
        PRIMARY KEY (Rnk, EffectiveYear)
);
INSERT @Results
SELECT  x.ID, 
        DENSE_RANK() OVER(ORDER BY x.[Tax Group], x.[Tax Type], x.[Geocode]) AS Rnk,
        x.EffectiveDate / 10000 AS EffectiveYear
FROM    @MyTable x;

SELECT  
        crt.*,
        prev.*,
        CASE 
            WHEN crt.ID IS NOT NULL AND prev.ID IS NOT NULL THEN '-' -- No change
            WHEN crt.ID IS NULL AND prev.ID IS NOT NULL THEN 'D' -- Deleted
            WHEN crt.ID IS NOT NULL AND prev.ID IS NULL THEN 'I' -- Inserted
        END AS RowStatus
FROM    @Results crt FULL OUTER JOIN @Results prev ON crt.Rnk = prev.Rnk
AND     crt.EffectiveYear - 1 = prev.EffectiveYear
ORDER BY ISNULL(crt.EffectiveYear - 1, prev.EffectiveYear), crt.Rnk;

示例输出:

---- ---- ------------- ---- ---- ------------- 
|     Current data    | |    Previous data    |  
---- ---- ------------- ---- ---- ------------- ---------
ID   Rnk  EffectiveYear ID   Rnk  EffectiveYear RowStatus
---- ---- ------------- ---- ---- ------------- ---------
1    1    112           NULL NULL NULL          I -- Current vs. previous: current row hasn't a previous row
3    2    112           NULL NULL NULL          I -- the same thing
4    3    112           NULL NULL NULL          I -- the same thing
2    4    112           NULL NULL NULL          I -- the same thing
NULL NULL NULL          4    3    112           D <-- Deleted: ID 4 = 'DGH'
5    1    113           1    1    112           - -- there is no change 
7    2    113           3    2    112           -
6    4    113           2    4    112           -
8    1    114           5    1    113           -
10   2    114           7    2    113           -
9    4    114           6    4    113           -
11   5    114           NULL NULL NULL          I <-- Inserted: ID 11 = 'Z9'
NULL NULL NULL          8    1    114           D 
NULL NULL NULL          10   2    114           D
NULL NULL NULL          9    4    114           D
NULL NULL NULL          11   5    114           D

注意:我假设一年内没有重复的行(x.[Tax Group], x.[Tax Type], x.[Geocode])。