有几种方法可以解决这个问题。
1.临时添加一列
正如其他人提到的,直接的方法是暂时将一列 reminder_id 添加到 dateset。使用来自reminder 表的原始IDs 填充它。使用它将reminder 与dateset 表连接起来。删除临时列。
2。何时开始是唯一的
如果start 列的值是唯一的,则可以通过将reminder 表与start 列上的dateset 表连接起来而无需额外的列。
INSERT INTO dateset (start)
SELECT start FROM reminder;
WITH
CTE_Joined
AS
(
SELECT
reminder.id AS reminder_id
,reminder.dateset_id AS old_dateset_id
,dateset.id AS new_dateset_id
FROM
reminder
INNER JOIN dateset ON dateset.start = reminder.start
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;
3.何时开始不是唯一的
即使在这种情况下,也可以在没有临时列的情况下执行此操作。主要思想如下。让我们看一下这个例子:
reminder 中有两行具有相同的 start 值和 ID 3 和 7:
reminder
id start dateset_id
3 2015-01-01 NULL
7 2015-01-01 NULL
我们将它们插入dateset后,会生成新的ID,例如1和2:
dateset
id start
1 2015-01-01
2 2015-01-01
我们如何链接这两行并不重要。最终结果可能是
reminder
id start dateset_id
3 2015-01-01 1
7 2015-01-01 2
或
reminder
id start dateset_id
3 2015-01-01 2
7 2015-01-01 1
这两种变体都是正确的。这给我们带来了以下解决方案。
只需先插入所有行。
INSERT INTO dateset (start)
SELECT start FROM reminder;
匹配/连接start 列上的两个表,知道它不是唯一的。通过添加ROW_NUMBER 并通过两列连接来“使其”独一无二。可以使查询更短,但我明确说明了每个步骤:
WITH
CTE_reminder_rn
AS
(
SELECT
id
,start
,dateset_id
,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
FROM reminder
)
,CTE_dateset_rn
AS
(
SELECT
id
,start
,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
FROM dateset
)
,CTE_Joined
AS
(
SELECT
CTE_reminder_rn.id AS reminder_id
,CTE_reminder_rn.dateset_id AS old_dateset_id
,CTE_dateset_rn.id AS new_dateset_id
FROM
CTE_reminder_rn
INNER JOIN CTE_dateset_rn ON
CTE_dateset_rn.start = CTE_reminder_rn.start AND
CTE_dateset_rn.rn = CTE_reminder_rn.rn
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;
我希望从代码中可以清楚地看出它的作用,尤其是当您将它与没有ROW_NUMBER 的更简单的版本进行比较时。显然,即使start 是唯一的,复杂的解决方案也可以工作,但它的效率不如简单的解决方案。
此解决方案假定dateset 在此过程之前为空。