基本上,我想将表 DET 复制到表 DET_NEW 。我知道 DET 有一些重复的行,所以我想只将重复的行插入一次。如您所见,我想使用 HDR 表按时间段复制这些行。
编辑以添加信息: DET 没有主键(这就是它具有重复行的原因)。 DET_NEW 具有包含 FK1 和 FK2 的复合主键。
问题:
我知道这不是一个新话题。我已经尝试了所有找到的解决方案,并且SQL Server返回了有关违反入门密钥约束的错误(“无法插入重复密钥”)。这些查询仅使用一个内核即可明确执行。
我看到MySQL具有INSERT IGNORE,但是我认为SQL Server中没有类似的东西。
我的解决方法如下:
查询1:
INSERT INTO DET_NEW
(FK1, FK2, value)
SELECT DISTINCT D.FK1, D.FK2, D.value
FROM HDR AS H,
DET AS D
WHERE H.Date >= CONVERT( datetime, '2015-01-01 00:00:00', 20 )
and H.Date < CONVERT( datetime, '2016-01-01 00:00:00', 20 )
and H.FK1 = D.FK1
查询2:
INSERT INTO DET_NEW
(FK1, FK2, value)
SELECT D.FK1, D.FK2, D.value
FROM
( SELECT DISTINCT D.FK1, D.FK2, D.value
FROM HDR AS H,
DET AS D
WHERE H.Date >= CONVERT( datetime, '2015-01-01 00:00:00', 20 )
and H.Date < CONVERT( datetime, '2016-01-01 00:00:00', 20 )
and H.FK1 = D.FK1
)D
查询3:
INSERT INTO DET_NEW
(FK1, FK2, value)
SELECT D.FK1, D.FK2, D.value
FROM HDR AS H,
DET AS D
WHERE H.Date >= CONVERT( datetime, '2018-02-01 00:00:00', 20 )
and H.Date < CONVERT( datetime, '2018-02-05 00:00:00', 20 )
and H.FK1 = D.FK1
GROUP BY D.FK1, D.FK2
查询4:
WITH cte AS (
SELECT D.FK1, D.FK2, D.value,
row_number() OVER(PARTITION BY D.FK1, D.FK2, D.value ORDER BY D.FK1) AS [rn]
FROM HDR AS H,
DET AS D
WHERE H.Date >= CONVERT( datetime, '2018-02-01 00:00:00', 20 )
and H.Date < CONVERT( datetime, '2018-02-03 00:00:00', 20 )
and H.FK1 = D.FK1
)
INSERT INTO DET_NEW
(FK1, FK2, value)
SELECT cte.FK1, cte.FK2, cte.value
FROM cte
WHERE cte.[rn] = 1
其他信息
我执行了以下查询:在外部,代码检查是否存在重复;在内部,有一个SELECT DISTINCT,与查询2相同。结果超过1k行,因此查询中出现了一些错误。
SELECT D.FK1, D.FK2, COUNT(D.FK1) AS count
FROM (
SELECT DISTINCT D.FK1, D.FK2, D.value
FROM HDR AS H,
DET AS D
WHERE H.Date >= CONVERT( datetime, '2018-02-01 00:00:00', 20 )
and H.Date < CONVERT( datetime, '2018-02-03 00:00:00', 20 )
and H.FK1 = D.FK1
)D
GROUP BY D.FK1, D.FK2
HAVING
COUNT(*) > 1
问题是:为什么要插入重复项?大型数据库(数十亿行)还有另一种有效的方法吗?
答案 0 :(得分:1)
INSERT INTO DET_NEW
(FK1, FK2, value)
SELECT K.FK1, K.FK2, K.value
FROM
(SELECT D.FK1, D.FK2, D.value,
ROW_NUMBER() OVER (PARTITION BY D.FK1, D.FK2 ORDER BY D.FK1, D.FK2) AS RN
FROM HDR AS H
JOIN DET AS D ON H.FK1 = D.FK1
WHERE H.Date >= CONVERT( datetime, '2015-01-01 00:00:00', 20 )
and H.Date < CONVERT( datetime, '2016-01-01 00:00:00', 20 )) K
WHERE K.RN=1
答案 1 :(得分:1)
对于1/N
和FK1
的某些组合,FK2
中可能有不止一个不同的value
。以下查询应证明
DET
您将需要在SELECT FK1, FK2, MIN(value), MAX(value), COUNT(DISTINCT value)
FROM DET
GROUP BY FK1, FK2
HAVING COUNT(DISTINCT value) > 1
的复合键中包含值,或者确定如何选择每个键要使用的值,例如使用DET_NEW
或MIN
。 @MoinulIslam提供的查询还将帮助您为每个键选择一个值。在该查询中,只是选择第一个。