将 SQL 服务器中的这些日期更新为每个 ID 的连续时间戳?
Update these dates in SQL Server to consecutive timestamps for each id?
我有 table 个 ID 和日期。我需要将日期转换为日期时间,但每个时间戳在该 ID 中都必须是唯一的。例如,如果这是我的 table:
ID
Date
0001
2020-03-21
0001
2020-03-21
0001
2020-03-21
0002
2020-03-21
0002
2020-03-21
然后我需要我的输出看起来像:
ID
Datetime
0001
2020-03-21 00:00:01
0001
2020-03-21 00:00:02
0001
2020-03-21 00:00:03
0002
2020-03-21 00:00:01
0002
2020-03-21 00:00:02
我很确定我们可以安全地假设没有 ID 在一天内有 86,400 个条目,所以我不必担心日期会意外滚动。
我认为光标可能是答案,但我是 SQL 的新手,并没有太多运气来弄清楚我将如何使用它。到目前为止,这是我尝试过的方法,但并没有让我达到我需要的目的:
SELECT TOP 1000 ROW_NUMBER() OVER(ORDER BY [CID] ASC,[XDATE] ASC) AS RN
,[CID]
,[XDATE]
,dateadd(second, ((ROW_NUMBER() OVER(ORDER BY [CID] ASC,[XDATE] ASC))%86400),cast([XDATE] as datetime)) AS NEW_DATE -- 86400 sec in a day so need to mod ROW_NUMBER to prevent changing the date
FROM entryTable
这个查询是连续加datetime的,也就是说偶尔会出现时间在同一天午夜翻滚,ID与最后一个entry相同的情况。这会导致我们最终数据库中的条目乱序,因为它根据时间戳对数据进行排序,然后显示为 post-midnight 的任何内容都将排在我们当前数据库中实际排在第一位的所有其他内容之前.
虽然您可能没有一个 ID 每天超过 86,400 个条目,但听起来您有足够的 ID 和足够的条目超过 86,400 总数。为了像您在问题中显示的那样重置行号,您需要将 PARTITION
应用于 window 函数:
SELECT TOP (1000) OverallRN = ROW_NUMBER() OVER (ORDER BY CID, XDATE)
,ROW_NUMBER() OVER
(PARTITION BY CID ORDER BY [XDATE]) AS RN
,[CID]
,[XDATE]
,dateadd(second, ROW_NUMBER() OVER
(PARTITION BY CID ORDER BY [XDATE]),cast([XDATE] as datetime)) AS NEW_DATE
FROM dbo.entryTable;
如果对于任何给定的 ID/日期组合,您仍然超过 86,400 个条目,您需要定义如何处理 86,401+,因为如果您想保持原始序列,它肯定不会 mod (%)
.也许您需要比一秒钟更细化,例如添加 ROW_NUMBER() * 100 milliseconds
。虽然如果这些是 table 中仅有的两列,我不知道你怎么知道任何东西都是乱序的。
使用这个
SELECT ID ,Date,
concat(Date,' ',DATEADD(second,
CAST(43200000 * (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) as int),
CAST('00:00:00' AS Time))) AS datetime
from entrytable
或更适合您的查询
SELECT TOP 1000 ROW_NUMBER() OVER(ORDER BY [CID] ASC,[XDATE] ASC) AS RN
,[CID]
,[XDATE]
, concat(Date,' ',DATEADD(second,
CAST(43200000 * (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) as int),
CAST('00:00:00' AS Time))) AS datetime
FROM entryTable
我有 table 个 ID 和日期。我需要将日期转换为日期时间,但每个时间戳在该 ID 中都必须是唯一的。例如,如果这是我的 table:
ID | Date |
---|---|
0001 | 2020-03-21 |
0001 | 2020-03-21 |
0001 | 2020-03-21 |
0002 | 2020-03-21 |
0002 | 2020-03-21 |
然后我需要我的输出看起来像:
ID | Datetime |
---|---|
0001 | 2020-03-21 00:00:01 |
0001 | 2020-03-21 00:00:02 |
0001 | 2020-03-21 00:00:03 |
0002 | 2020-03-21 00:00:01 |
0002 | 2020-03-21 00:00:02 |
我很确定我们可以安全地假设没有 ID 在一天内有 86,400 个条目,所以我不必担心日期会意外滚动。
我认为光标可能是答案,但我是 SQL 的新手,并没有太多运气来弄清楚我将如何使用它。到目前为止,这是我尝试过的方法,但并没有让我达到我需要的目的:
SELECT TOP 1000 ROW_NUMBER() OVER(ORDER BY [CID] ASC,[XDATE] ASC) AS RN
,[CID]
,[XDATE]
,dateadd(second, ((ROW_NUMBER() OVER(ORDER BY [CID] ASC,[XDATE] ASC))%86400),cast([XDATE] as datetime)) AS NEW_DATE -- 86400 sec in a day so need to mod ROW_NUMBER to prevent changing the date
FROM entryTable
这个查询是连续加datetime的,也就是说偶尔会出现时间在同一天午夜翻滚,ID与最后一个entry相同的情况。这会导致我们最终数据库中的条目乱序,因为它根据时间戳对数据进行排序,然后显示为 post-midnight 的任何内容都将排在我们当前数据库中实际排在第一位的所有其他内容之前.
虽然您可能没有一个 ID 每天超过 86,400 个条目,但听起来您有足够的 ID 和足够的条目超过 86,400 总数。为了像您在问题中显示的那样重置行号,您需要将 PARTITION
应用于 window 函数:
SELECT TOP (1000) OverallRN = ROW_NUMBER() OVER (ORDER BY CID, XDATE)
,ROW_NUMBER() OVER
(PARTITION BY CID ORDER BY [XDATE]) AS RN
,[CID]
,[XDATE]
,dateadd(second, ROW_NUMBER() OVER
(PARTITION BY CID ORDER BY [XDATE]),cast([XDATE] as datetime)) AS NEW_DATE
FROM dbo.entryTable;
如果对于任何给定的 ID/日期组合,您仍然超过 86,400 个条目,您需要定义如何处理 86,401+,因为如果您想保持原始序列,它肯定不会 mod (%)
.也许您需要比一秒钟更细化,例如添加 ROW_NUMBER() * 100 milliseconds
。虽然如果这些是 table 中仅有的两列,我不知道你怎么知道任何东西都是乱序的。
使用这个
SELECT ID ,Date,
concat(Date,' ',DATEADD(second,
CAST(43200000 * (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) as int),
CAST('00:00:00' AS Time))) AS datetime
from entrytable
或更适合您的查询
SELECT TOP 1000 ROW_NUMBER() OVER(ORDER BY [CID] ASC,[XDATE] ASC) AS RN
,[CID]
,[XDATE]
, concat(Date,' ',DATEADD(second,
CAST(43200000 * (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) as int),
CAST('00:00:00' AS Time))) AS datetime
FROM entryTable