存储在SQL Server中维护排序索引的计算列的最佳方法是什么?

时间:2014-06-14 19:01:38

标签: sql sql-server sorting

所以,假设我有一个名为[transactions]的表,其中包含一个标识列作为主键,一个日期字段和一些其他列。我想要包含一个计算或以某种方式计算的持久列,它将有效地存储“排序顺序”。但是,这不能仅仅是ID列,因为我按日期排序,有时您可能会追溯性地添加值。

例如,如果表格看起来像这样:

+-----+------------+---------+--------+--------+
| id  |    date    | account | amount | (sort) |
+-----+------------+---------+--------+--------+
|   1 | 2014-05-22 |      7  | 100.00 |    1   |
|   2 | 2014-05-29 |      7  |  45.25 |    2   |
|   3 | 2014-06-03 |      8  |  99.00 |    3   |
+-----+------------+---------+--------+--------+

然后,如果我运行此声明:

INSERT INTO [transactions] ([date], [account], [amount]) 
VALUES ('2014-05-27', 8, 88.50);

我希望sort列足够智能,以便表格看起来像这样:

+-----+------------+---------+--------+--------+
| id  |    date    | account | amount | (sort) |
+-----+------------+---------+--------+--------+
|   1 | 2014-05-22 |      7  | 100.00 |    1   |
|   2 | 2014-05-29 |      7  |  45.25 |    3   |
|   3 | 2014-06-03 |      8  |  99.00 |    4   |
|   4 | 2014-05-27 |      8  |  88.50 |    2   |
+-----+------------+---------+--------+--------+

理想情况下,我希望此列能够作为实际列保留。实现这一目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:3)

您可以在需要时计算该值:

select t.*, row_number() over (order by [date]) as [sort]
from transactions t;

或者,只需对[date]使用order by即可。我不明白为什么需要另一栏。

编辑:

如果您想保持列sort按顺序排列,那么您将需要一个触发器。并且,触发器不会便宜。触发器中的逻辑基本上是:

update transactions
    set sort = sort + 1
    where [date] > NEWDATE;

insert into transactions( . . . , [sort])
    select . . . , coalesce(max([sort])) + 1
    from transactions
    where [date] < NEWDATE;

(我遗漏了定义触发器所涉及的所有内容。)

尽管使用索引可以使insert非常有效,但这确实会影响update的性能,{{1}}必须影响具有更大日期的每一行。如果您几乎总是插入具有较新日期的行,这可能是一个合理的权衡。