我正在尝试从没有主键的现有数据仓库表(OldTable
(创建维度表(NewTable
(。
OldTable
在[IdentifierCode]
中保存不同的值,其他值在它周围重复。我还需要调用3个函数来添加报告上下文。
我希望IdentifierCode_ID
是INT列,因为[IdentifierCode]
列是VARCHAR(6)
。
我的问题是:使用ROW_NUMBER()
(如下所示(是否会产生一个适当的唯一值?
我担心的是,如果插入其他行以修正遗漏的代码,则活动表上的行顺序可能会更改。
编辑:OldTable
总共有500k行,使用WHERE
子句过滤时有227k行
SELECT
ROW_NUMBER() OVER (ORDER BY LoadDate, StartDate, Product, IdentifierCode) AS IdentifierCode_ID,
LoadDate,
StartDate,
EndDate,
Product,
IdentifierCode,
OtherField1, OtherField2, OtherField3, OtherField4,
Function1, Function2, Function3
INTO
NewTable
FROM
OldTable
WHERE
GETDATE() BETWEEN StartDate AND EndDate
首先,除非您加载一次数据,然后再也不接触它,或者在每次加载新的日期范围之前截断NewTable,否则您的方法将不起作用。ROW_NUMBER将在1重新启动并违反主键。
即使您正在截断表或只加载一次,仍然有更好的方法。将IdentifierCode_ID
指定为"标识"列,SQL将为您处理它。如果类型为INT并且设置了IDENTITY,则在插入新行时,SQL将自动在最后一个值上加1,您甚至不必分配它!
CREATE TABLE dbo.NewTable(
[IdentifierCode_ID] int IDENTITY(1,1) NOT NULL,
[IdentifierCode] VARCHAR(6) NOT NULL,
...
此外,如果意外地为后续加载选择了一个重叠的日期范围,并且OldTable中的值发生了变化,请确保考虑到您将要做什么——例如,向WHERE子句添加一个限制,以从插入中排除现有的IdentifierCode
值,并添加第二个查询,以更新具有不同LoadDate
、StartDate
等的现有IdentifierCode
值。
...
AND NOT EXISTS (SELECT * FROM NewTable as N WHERE N.IdentifierCode = OldTable.IdentifierCode)
为了更新已更改的现有行,可以执行INNER JOIN以仅选择现有行,并为已更改的行执行WHERE子句。
UPDATE NewTable
SET LoadDate = O.LoadDate, StartDate = O.StartDate, ... --don't forget to recalculate the functions!
FROM NewTable as N INNER JOIN OldTable as O on N.IdentifierCode = O.IdentifierCode
WHERE GETDATE() between O.StartDate and O.EndDate
AND NOT (N.StartDate = O.StartDate and N.EndDate = O.EndDate ... )