SQL JOIN with COALESCE 的条件是重复行
SQL JOIN with COALESCE in condition is duplicating rows
我正在尝试将两个 table 连接在一起。第一个 table 包含我不想复制的数据记录。第二个 table 我加入第一个 table 以通过不同的 [profileId] 和 [role] 查找 [value]。第二个 table 中的 [profileId]、[role] 列对组合具有唯一约束,但 [role] 有时可以为 NULL,在这种情况下,我将该值视为该配置文件的默认值。
如何在不复制行且不使用多个左连接的情况下将这些 table 连接在一起?我的实际查询比示例更复杂。
请参阅下面的示例。
DECLARE @temp TABLE ([profileId] int, [role] int)
DECLARE @temp2 TABLE ([profileId] int, [role] int, [value] nvarchar(50))
INSERT INTO @temp ([profileId], [role]) VALUES (1, 1)
INSERT INTO @temp ([profileId], [role]) VALUES (1, 2)
INSERT INTO @temp ([profileId], [role]) VALUES (2, 1)
INSERT INTO @temp ([profileId], [role]) VALUES (2, 2)
INSERT INTO @temp2 ([profileId], [role], [value]) VALUES (1, 1, 'MATCH')
INSERT INTO @temp2 ([profileId], [role], [value]) VALUES (1, NULL, 'DEFAULT1')
INSERT INTO @temp2 ([profileId], [role], [value]) VALUES (2, NULL, 'DEFAULT2')
SELECT
T1.[profileId],
T1.[role],
T2.value
FROM
@temp T1
JOIN @temp2 T2 ON T1.profileId = T2.profileId AND COALESCE(T2.[role], T1.[role]) = T1.[role]
这给了我(我明白为什么)
================================
| profileId | role | value |
================================
| 1 | 1 | MATCH |
--------------------------------
| 1 | 1 | DEFAULT1 |
--------------------------------
| 1 | 2 | DEFAULT1 |
--------------------------------
| 2 | 1 | DEFAULT2 |
--------------------------------
| 2 | 2 | DEFAULT2 |
================================
虽然我想要
================================
| profileId | role | value |
================================
| 1 | 1 | MATCH |
--------------------------------
| 1 | 2 | DEFAULT1 |
--------------------------------
| 2 | 1 | DEFAULT2 |
--------------------------------
| 2 | 2 | DEFAULT2 |
================================
如果您知道 DEFAULT
值,请使用 left join
。
SELECT
T1.[role],
COALESCE(T2.value, 'DEFAULT') as value
FROM
temp T1
LEFT JOIN temp2 T2
ON T1.[role] = T2.[role];
否则
SELECT
T1.[role],
COALESCE(T2.value, (SELECT value
FROM temp2
WHERE role is NULL and temp2.profileID = T1.profileID)) as value
FROM
temp T1
LEFT JOIN temp2 T2
ON T1.[role] = T2.[role]
AND T1.[profileID] = T2.[profileID]
;
这个 SQL 工作正常:
SELECT
T1.[role],
Value = coalesce(max(nullif(T2.value,'DEFAULT')),'DEFAULT')
FROM
@temp T1
JOIN @temp2 T2 ON COALESCE(T2.[role], T1.[role]) = T1.[role]
group by
T1.[role]
;
您可以使用 APPLY
和 TOP
:
SELECT
t.profileId,
t.role,
x.value
FROM @temp t
OUTER APPLY(
SELECT TOP 1 value
FROM @temp2
WHERE
profileId = t.profileId
AND (role = t.role OR role IS NULL)
ORDER BY
CASE WHEN role IS NOT NULL THEN 0 ELSE 1 END
)x
我正在尝试将两个 table 连接在一起。第一个 table 包含我不想复制的数据记录。第二个 table 我加入第一个 table 以通过不同的 [profileId] 和 [role] 查找 [value]。第二个 table 中的 [profileId]、[role] 列对组合具有唯一约束,但 [role] 有时可以为 NULL,在这种情况下,我将该值视为该配置文件的默认值。
如何在不复制行且不使用多个左连接的情况下将这些 table 连接在一起?我的实际查询比示例更复杂。
请参阅下面的示例。
DECLARE @temp TABLE ([profileId] int, [role] int)
DECLARE @temp2 TABLE ([profileId] int, [role] int, [value] nvarchar(50))
INSERT INTO @temp ([profileId], [role]) VALUES (1, 1)
INSERT INTO @temp ([profileId], [role]) VALUES (1, 2)
INSERT INTO @temp ([profileId], [role]) VALUES (2, 1)
INSERT INTO @temp ([profileId], [role]) VALUES (2, 2)
INSERT INTO @temp2 ([profileId], [role], [value]) VALUES (1, 1, 'MATCH')
INSERT INTO @temp2 ([profileId], [role], [value]) VALUES (1, NULL, 'DEFAULT1')
INSERT INTO @temp2 ([profileId], [role], [value]) VALUES (2, NULL, 'DEFAULT2')
SELECT
T1.[profileId],
T1.[role],
T2.value
FROM
@temp T1
JOIN @temp2 T2 ON T1.profileId = T2.profileId AND COALESCE(T2.[role], T1.[role]) = T1.[role]
这给了我(我明白为什么)
================================
| profileId | role | value |
================================
| 1 | 1 | MATCH |
--------------------------------
| 1 | 1 | DEFAULT1 |
--------------------------------
| 1 | 2 | DEFAULT1 |
--------------------------------
| 2 | 1 | DEFAULT2 |
--------------------------------
| 2 | 2 | DEFAULT2 |
================================
虽然我想要
================================
| profileId | role | value |
================================
| 1 | 1 | MATCH |
--------------------------------
| 1 | 2 | DEFAULT1 |
--------------------------------
| 2 | 1 | DEFAULT2 |
--------------------------------
| 2 | 2 | DEFAULT2 |
================================
如果您知道 DEFAULT
值,请使用 left join
。
SELECT
T1.[role],
COALESCE(T2.value, 'DEFAULT') as value
FROM
temp T1
LEFT JOIN temp2 T2
ON T1.[role] = T2.[role];
否则
SELECT
T1.[role],
COALESCE(T2.value, (SELECT value
FROM temp2
WHERE role is NULL and temp2.profileID = T1.profileID)) as value
FROM
temp T1
LEFT JOIN temp2 T2
ON T1.[role] = T2.[role]
AND T1.[profileID] = T2.[profileID]
;
这个 SQL 工作正常:
SELECT
T1.[role],
Value = coalesce(max(nullif(T2.value,'DEFAULT')),'DEFAULT')
FROM
@temp T1
JOIN @temp2 T2 ON COALESCE(T2.[role], T1.[role]) = T1.[role]
group by
T1.[role]
;
您可以使用 APPLY
和 TOP
:
SELECT
t.profileId,
t.role,
x.value
FROM @temp t
OUTER APPLY(
SELECT TOP 1 value
FROM @temp2
WHERE
profileId = t.profileId
AND (role = t.role OR role IS NULL)
ORDER BY
CASE WHEN role IS NOT NULL THEN 0 ELSE 1 END
)x