如何为每一行将 DateTime 列增加一秒?

Posted

技术标签:

【中文标题】如何为每一行将 DateTime 列增加一秒?【英文标题】:How to increment DateTime column by a second for every row? 【发布时间】:2013-03-28 21:52:33 【问题描述】:

假设我有这个时间值:09:00:00

我有一个包含时间列的表,其中包含三条记录。

我想用那个时间更新这 3 条记录,但每次(对于每条记录)时间值都会增加一秒。

类似这样的:

ColumnA   ColumnB
1         09:00:00
2         09:00:01
3         09:00:02

我该怎么做?

我的解决方案:

在我自己的解决方案工作了一段时间后,这就是我想出的

update tor1
set ColumnB = dateadd(s,tor2.inc, ColumnB)
from table1 tor1
inner join (select ColumnA, ROW_NUMBER() OVER (Order by ColumnA) as inc from table1) tor2 on tor1.ColumnA=tor2.ColumnA

【问题讨论】:

如果我们不能使用ColumnA来订购,你如何建议我们知道哪一行加0秒,哪一行加1,哪一行加2?表是一组无序的行,因此如果您想要一个可预测的结果,您需要指明该顺序是如何定义的。 假设ColumnA 是PK,它是身份。现在假设第 2 条记录被删除了,你会给第 3 行加 2 秒吗? 您是否在问自己自己的要求是什么? 我只想将秒 (1++) 添加到该列 B,而不管其他列。第一行,同一时间,第二行+1,第三行2,以此类推 @Somebody 既然你已经有了答案,那么十亿美元的问题就是你为什么要这样做? 【参考方案1】:

您没有指定任何特定的顺序。

对于不确定/未记录的结果,您可以尝试古怪的更新方法。

CREATE TABLE table1
(
    ColumnB datetime NULL
);

INSERT INTO table1 DEFAULT VALUES;
INSERT INTO table1 DEFAULT VALUES;
INSERT INTO table1 DEFAULT VALUES;

DECLARE @ColumnB datetime;

SET @ColumnB = '19000101 09:00:00';

UPDATE table1
SET @ColumnB = ColumnB = DATEADD(s, 1, @ColumnB);

SELECT *
FROM table1;

DROP TABLE table1;

否则,您将需要使用光标或找到某种方法来模拟 2000 年的ROW_NUMBER

【讨论】:

@mattedgod - 虽然它没有记录/保证(如果依赖于任何类型的确定性排序尤其脆弱),并且应该在更高版本中更全面地实现 OVER 子句时过时。一篇关于 SQL Server 中心的有趣文章 Solving the Running Total and Ordinal Rank Problems (Rewritten)。但是,如果 OP 只是设置测试数据,例如应该没问题。 Richard 身体变形了,因为您的 DECLARE 行在 2000 年不起作用。 @RichardTheKiwi - 保证根据ORDER 子句分配IDENTITY 值。不保证插入按任何特定顺序。 2012年this shows up more as it often used to follow the ORDER BY just in case the plan was run with SET ROWCOUNT N【参考方案2】:

这是一个使用 #temp 表但不使用不受支持的古怪更新(无意冒犯 Martin)并且不依赖于无法保证的神奇身份排序的版本(无意冒犯 Richard)。

CREATE TABLE dbo.Whatever
(
  ColumnA INT IDENTITY(1,1), 
  ColumnB DATETIME
);

INSERT dbo.Whatever(ColumnB) SELECT '09:00';
INSERT dbo.Whatever(ColumnB) SELECT '09:00';
INSERT dbo.Whatever(ColumnB) SELECT '09:00';
INSERT dbo.Whatever(ColumnB) SELECT '09:00';
INSERT dbo.Whatever(ColumnB) SELECT '09:00';

-- just to demonstrate a gap
DELETE dbo.Whatever WHERE ColumnA = 3;

SELECT w.ColumnA, w.ColumnB, 
  c = (SELECT COUNT(*) FROM dbo.Whatever WHERE ColumnA < w.ColumnA)
INTO #x
 FROM dbo.Whatever AS w;

UPDATE w
  SET ColumnB = DATEADD(SECOND, x.c, w.ColumnB)
  FROM dbo.Whatever AS w
  INNER JOIN #x AS x
  ON x.ColumnA = w.ColumnA;

SELECT ColumnA, ColumnB FROM dbo.Whatever;

结果:

ColumnA  ColumnB
-------  -----------------------
1        1900-01-01 09:00:00.000
2        1900-01-01 09:00:01.000
4        1900-01-01 09:00:02.000
5        1900-01-01 09:00:03.000

【讨论】:

可能不建议用于大型表,因为 SELECT COUNT(*) 子查询使其 O(n^2)。但否则一个很好的解决方案如果 ColumnA 是唯一的(OP 没有说明)。 OP 声明它是一个身份列。虽然这本身并不能保证唯一性,但我只看到由于故意破坏或极端愚蠢而导致的重复。 OP 提出了一个问题“如果......是一个身份”。 OP还在mattedgod的回答下说“认为该列甚至不存在”。当然,在这种情况下我的解决方案也行不通【参考方案3】:

如果您可以假设 ColumnA 是您需要添加的秒数(或像您的示例那样成正比),那么您可以使用它。

UPDATE myTable SET ColumnB = DATEADD(s, (ColumnA - 1), ColumnB)

如果没有,您将需要确定每列的排名(谷歌上有很多结果)并添加排名。

【讨论】:

遗憾的是,我不能将该列用作增量值。此外认为该列甚至不存在 @Somebody 哪一栏不存在? A 列?您将其包含在示例中...如果不是 ColumnA,请提供一种确定顺序的方法,我们还应该如何知道?【参考方案4】:

对于 SQL Server 2005 及更高版本,您可以使用 OVER 子句来控制更新的顺序。

;with T as (
    select *, rn=row_number() over (order by columnA)
    from Tbl)
update T
    set columnB = DateAdd(s, rn-1, '09:00:00');

SQL Fiddle

对于 SQL Server 2000,您可以使用临时表。使用INSERT INTO..SELECT to guarantee IDENTITY 列的计算。

CREATE TABLE table1
(
    ColumnA int,
    ColumnB datetime NULL
);

INSERT INTO table1 values (1, null);
INSERT INTO table1 values (2, getdate());
INSERT INTO table1 values (3, '02:02:02');

create table #tmp (ColumnA int, ID int identity(0,1))

insert into #tmp
select ColumnA
from table1
order by ColumnA;

update a
set ColumnB = dateadd(s,t.ID,'09:00:00')
from #tmp t
join table1 a on a.ColumnA = t.ColumnA;

select * from table1;

【讨论】:

这是一个定义了 IDENTITY 列的表。您正在使用不同的 IDENTITY 函数。 support.microsoft.com/default.aspx?scid=kb;en-us;Q273586 我认为也可能存在涉及并行性和身份值分配方式的错误,所以如果你要依赖你所观察到的,请使用MAXDOP 1。对于 OP 的示例(三行),这不是问题,但我们真的不知道我们在谈论多少行。 @RichardTheKiwi - 我认为 Aaron 的观点是文章保证顺序但不保证顺序。 另见sqlmag.com/article/sql-server/…(关于 IDENTITY() 函数)。 @Aaron 我想我们已经在几条评论前移除了 IDENTITY() 函数

以上是关于如何为每一行将 DateTime 列增加一秒?的主要内容,如果未能解决你的问题,请参考以下文章

如何明智地将列增加一组

如何为表格的每一行创建展开/折叠功能?角6

如何为表格的每一行放置一个表格

如何为rdd的每一行生成一个哈希? (PYSPARK)

如何为网格面板中的每一行创建一个表单:extjs

如何为数据表的每一行添加按钮?