所以,假设我有一个名为[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 |
+-----+------------+---------+--------+--------+
理想情况下,我希望此列能够作为实际列保留。实现这一目标的最佳方法是什么?
答案 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}}必须影响具有更大日期的每一行。如果您几乎总是插入具有较新日期的行,这可能是一个合理的权衡。