【问题标题】:How to track changes in records in SQL Server?如何跟踪 SQL Server 中记录的变化?
【发布时间】:2017-04-07 05:42:36
【问题描述】:

我有下表,其中有所有学生的跟踪记录。

|==========================================|
| ID      |  Department     | Date         |
|==========================================|
| 001     | English         | Feb 3 2017   |
| 001     | English         | Feb 4 2017   |
| 001     | Science         | Mar 1 2017   |
| 001     | Science         | Apr 2 2017   |
| 001     | Maths           | Apr 7 2017   |
| 002     | Maths           | Feb 1 2017   |
| 002     | Maths           | Apr 7 2017   |
| 003     | Maths           | Apr 3 2017   |
| 004     | Science         | Feb 1 2017   |
| 004     | Maths           | Apr 7 2017   |
|==========================================| 

我需要在学生更改部门之前获取之前的记录。对于上面的例子,返回的记录集应该是

对于 001,

| 001     | English         | Feb 4 2017   |
| 001     | Science         | Apr 2 2017   |

对于 002 和 003

没有变化

004

| 004     | Science         | Feb 1 2017   |

同一用户也有可能改回同一部门。例如,user001 可以从部门 a 更改为部门 b 到部门 c 并返回到部门 a。我已阅读有关 T-SQL 发送和接收的信息。但不确定这在这种情况下是否有帮助。请帮忙。

【问题讨论】:

  • SQL Server 的版本是多少?
  • 我不明白;您想查询表以查找这些记录,还是想在 INSERT 或 UPDATE 发生时立即获取这些记录?
  • @GiorgosAltanis 每当部门在历史上发生变化时,它都必须获取记录集。与 001 一样,系已从英语-科学更改为 2 月 4 日。同样,他已从科学-数学更改为 4 月 4 日。这适用于所有 ID
  • @VladimirBaranov 版本是 2012
  • 那么,现在你有了答案,发送和接收是什么?

标签: sql sql-server sql-server-2012


【解决方案1】:

一种方法是使用带有分区的ROW_NUMBER 函数来检测Department 列的值何时发生变化。

样本数据

DECLARE @T TABLE (ID int, Department nvarchar(100), dt date);
INSERT INTO @T (ID, Department, dt) VALUES
(1, 'English', 'Feb 3 2017'),
(1, 'English', 'Feb 4 2017'),
(1, 'Science', 'Mar 1 2017'),
(1, 'Science', 'Apr 2 2017'),
(1, 'Maths  ', 'Apr 7 2017'),
(2, 'Maths  ', 'Feb 1 2017'),
(2, 'Maths  ', 'Apr 7 2017'),
(3, 'Maths  ', 'Apr 3 2017'),
(4, 'Science', 'Feb 1 2017'),
(4, 'Maths  ', 'Apr 7 2017');

查询

WITH
CTE
AS
(
    SELECT
        ID
        ,Department
        ,dt
        ,ROW_NUMBER() OVER (PARTITION BY ID, Department ORDER BY dt DESC) AS rnPart
        ,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY dt DESC) AS rnID
    FROM @T
)
SELECT
    ID
    ,Department
    ,dt
FROM CTE
WHERE
    rnPart = 1
    AND rnID <> 1
ORDER BY
    ID
    ,dt
;

结果

+----+------------+------------+
| ID | Department |     dt     |
+----+------------+------------+
|  1 | English    | 2017-02-04 |
|  1 | Science    | 2017-04-02 |
|  4 | Science    | 2017-02-01 |
+----+------------+------------+

【讨论】:

  • dt 重命名为 date 以匹配 Poppy 的列名。干得好!
  • @GiorgosAltanis,这只是一个例子。我不喜欢在列名中使用保留字。
  • 我理解(并且我同意)。当我编辑您的答案时,您尚未提供示例代码,因此我想确保 OP 了解此解决方案有效。
  • @VladimirBaranov 如果学生从 A 部门(过去)再次转到 A 部门,分区将如何工作。
  • @Poppy,你的意思是从 A 到 B,然后从 B 回到 A,然后到 C?在这种情况下,我的查询将只返回 A 的最后日期。它不会返回两行 A。我认为如果您问另一个问题,其中包含涵盖所有重要案例的更广泛的样本数据,那会更好。如果我理解正确,那么查询将完全不同并且更复杂。
【解决方案2】:

这可以通过在您需要跟踪的表上创建插入/更新后触发器来完成。使用 sql server 中的逻辑表 Inserted/Deleted,您可以跟踪表上新插入和修改的字段。

已插入(逻辑表):它将为您提供新插入的记录/更新值(列值)的详细信息。

已删除(逻辑表):它会在字段被修改/删除之前为您提供旧值。

【讨论】:

    【解决方案3】:

    我不太确定,但您可以就存储过程的概念获得帮助。它们是作为数据库一部分的函数。查询时可以设置显示

    【讨论】:

      猜你喜欢
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-04
      • 2016-10-29
      • 1970-01-01
      • 2017-06-01
      相关资源
      最近更新 更多