SQL 服务器 - 合并时合并重复键上的数据
SQL Server - coalesce data on duplicate keys when MERGE-ing
我偶然发现了一个恼人的情况,即我的源查询结果具有包含不同数据的重复键。不幸的是,我需要回填任何 NULL。
我尝试使用 MERGE
但出现关键错误。
MySQL 中的等效查询(我无法转换)是:
请注意,我已经更改了所有字段和 table 名称
INSERT INTO user_brief (name, high_score, colour)
SELECT
u.name,
h.high_score,
p.colour,
FROM foo_table AS f
LEFT JOIN users AS u ON f.user_id = u.id
LEFT JOIN high_scores AS h ON f.user_id = h.id
LEFT JOIN preferences AS p ON f.user_id = p.id
ON DUPLICATE KEY
UPDATE
name = COALESCE(user_brief.name, VALUES(name)),
high_score = COALESCE(user_brief.high_score, VALUES(high_score)),
colour = COALESCE(user_brief.colour, VALUES(colour));
SELECT 查询结果
如果我们只取 SELECT 你会得到以下结果:
name | high_score | color
---------------------------
foo | NULL | brown
foo | 40 | NULL
bar | 29 | blue
...
想要的结果
name | high_score | color
---------------------------
foo | 40 | brown
bar | 29 | blue
...
如您所见,它已变平(不确定这是否是正确的术语)为 name
键控记录的每一列取第一个非空值。
我尝试的 MERGE
解决方案(但出现关键错误):
MERGE INTO user_brief AS target
USING (SELECT
u.name,
h.high_score,
p.colour,
FROM foo_table AS f
LEFT JOIN users AS u ON f.user_id = u.id
LEFT JOIN high_scores AS h ON f.user_id = h.id
LEFT JOIN preferences AS p ON f.user_id = p.id) AS source
ON target.name = source.name
WHEN MATCHED THEN
UPDATE SET
target.name = COALESCE(source.name, target.name),
target.high_score = COALESCE(source.high_score, target.high_score),
target.colour = COALESCE(source.colour, target.colour)
WHEN NOT MATCHED BY TARGET THEN
INSERT (name, high_score, colour)
VALUES (source.name, source.high_score, source.colour);
您可以使用 GROUP BY
来扁平化源代码:
WITH source AS (
SELECT
u.name,
high_score = MIN(h.high_score),
colour = MIN(p.colour)
FROM foo_table AS f
LEFT JOIN users AS u ON f.user_id = u.id
LEFT JOIN high_scores AS h ON f.user_id = h.id
LEFT JOIN preferences AS p ON f.user_id = p.id
GROUP BY u.name
)
MERGE INTO user_brief AS target
USING source
ON target.name = source.name
WHEN MATCHED THEN
UPDATE SET
target.name = COALESCE(source.name, target.name),
target.high_score = COALESCE(source.high_score, target.high_score),
target.colour = COALESCE(source.colour, target.colour)
WHEN NOT MATCHED BY TARGET THEN
INSERT (name, high_score, colour)
VALUES (source.name, source.high_score, source.colour);
我偶然发现了一个恼人的情况,即我的源查询结果具有包含不同数据的重复键。不幸的是,我需要回填任何 NULL。
我尝试使用 MERGE
但出现关键错误。
MySQL 中的等效查询(我无法转换)是:
请注意,我已经更改了所有字段和 table 名称
INSERT INTO user_brief (name, high_score, colour)
SELECT
u.name,
h.high_score,
p.colour,
FROM foo_table AS f
LEFT JOIN users AS u ON f.user_id = u.id
LEFT JOIN high_scores AS h ON f.user_id = h.id
LEFT JOIN preferences AS p ON f.user_id = p.id
ON DUPLICATE KEY
UPDATE
name = COALESCE(user_brief.name, VALUES(name)),
high_score = COALESCE(user_brief.high_score, VALUES(high_score)),
colour = COALESCE(user_brief.colour, VALUES(colour));
SELECT 查询结果
如果我们只取 SELECT 你会得到以下结果:
name | high_score | color
---------------------------
foo | NULL | brown
foo | 40 | NULL
bar | 29 | blue
...
想要的结果
name | high_score | color
---------------------------
foo | 40 | brown
bar | 29 | blue
...
如您所见,它已变平(不确定这是否是正确的术语)为 name
键控记录的每一列取第一个非空值。
我尝试的 MERGE
解决方案(但出现关键错误):
MERGE INTO user_brief AS target
USING (SELECT
u.name,
h.high_score,
p.colour,
FROM foo_table AS f
LEFT JOIN users AS u ON f.user_id = u.id
LEFT JOIN high_scores AS h ON f.user_id = h.id
LEFT JOIN preferences AS p ON f.user_id = p.id) AS source
ON target.name = source.name
WHEN MATCHED THEN
UPDATE SET
target.name = COALESCE(source.name, target.name),
target.high_score = COALESCE(source.high_score, target.high_score),
target.colour = COALESCE(source.colour, target.colour)
WHEN NOT MATCHED BY TARGET THEN
INSERT (name, high_score, colour)
VALUES (source.name, source.high_score, source.colour);
您可以使用 GROUP BY
来扁平化源代码:
WITH source AS (
SELECT
u.name,
high_score = MIN(h.high_score),
colour = MIN(p.colour)
FROM foo_table AS f
LEFT JOIN users AS u ON f.user_id = u.id
LEFT JOIN high_scores AS h ON f.user_id = h.id
LEFT JOIN preferences AS p ON f.user_id = p.id
GROUP BY u.name
)
MERGE INTO user_brief AS target
USING source
ON target.name = source.name
WHEN MATCHED THEN
UPDATE SET
target.name = COALESCE(source.name, target.name),
target.high_score = COALESCE(source.high_score, target.high_score),
target.colour = COALESCE(source.colour, target.colour)
WHEN NOT MATCHED BY TARGET THEN
INSERT (name, high_score, colour)
VALUES (source.name, source.high_score, source.colour);