如何在SQL中实现这种连接?
如何在SQL中实现这种连接 表1如何在SQL中实现这种连接?,sql,sql-server,join,Sql,Sql Server,Join,如何在SQL中实现这种连接 表1 +----+-----------+-----------+---------+ | ID | FILTER1 | FILTER2 | DATA1 | | 1 | filter1-A | filter2-A | data1-A | | 2 | filter1-B | filter2-B | data1-B | +----+-----------+-----------+---------+ 表2 +----+-----------+------
+----+-----------+-----------+---------+
| ID | FILTER1 | FILTER2 | DATA1 |
| 1 | filter1-A | filter2-A | data1-A |
| 2 | filter1-B | filter2-B | data1-B |
+----+-----------+-----------+---------+
表2
+----+-----------+-----------+---------+
| ID | FILTER1 | FILTER2 | DATA1 |
| 1 | filter1-B | filter2-B | data2-B |
| 2 | filter1-C | filter2-C | data2-C |
+----+-----------+-----------+---------+
结果
+------------+-----------+---------+---------+
| FILTER1 | FILTER2 | DATA1 | DATA2 |
| filter1-A | filter2-A | data1-A | NULL |
| filter1-B | filter2-B | data1-B | data2-B |
| filter1-C | filter2-C | NULL | data2-C |
+------------+-----------+---------+---------+
这称为完全外部联接
SELECT
ISNULL(T1.FILTER1, T2.FILTER1) AS FILTER_1,
ISNULL(T1.FILTER2, T2.FILTER2) AS FILTER_2,
T1.DATA1 AS DATA_1,
T2.DATA1 AS DATA_2
FROM TABLE1 T1
FULL OUTER JOIN TABLE2 T2
ON T1.FILTER1 = T2.FILTER1
AND T1.FILTER2 = T2.FILTER2
这称为完全外部联接
SELECT
ISNULL(T1.FILTER1, T2.FILTER1) AS FILTER_1,
ISNULL(T1.FILTER2, T2.FILTER2) AS FILTER_2,
T1.DATA1 AS DATA_1,
T2.DATA1 AS DATA_2
FROM TABLE1 T1
FULL OUTER JOIN TABLE2 T2
ON T1.FILTER1 = T2.FILTER1
AND T1.FILTER2 = T2.FILTER2
FULL OUTER JOIN
保留每个表中的每个记录,而不管另一个表中是否有匹配项
然后可以使用COALESCE()
SELECT G.FILTER1, G.FILTER2, T1.DATA1, T2.DATA1 as DATA2 FROM
(SELECT FILTER1, FILTER2
FROM TABLE1
UNION
SELECT FILTER1, FILTER2
FROM TABLE2
GROUP BY FILTER1, FILTER2) as G
LEFT JOIN TABLE1 as T1 ON T1.FILTER1 = G.FILTER1 AND T1.FILTER2 = G.FILTER2
LEFT JOIN TABLE2 as T2 ON T2.FILTER1 = G.FILTER1 AND T2.FILTER2 = G.FILTER2
FULL OUTER JOIN
保留每个表中的每个记录,而不管另一个表中是否有匹配项
然后可以使用COALESCE()
(有些使用ISNULL()
)来扫描缺少的/NULL值,以找到第一个非NULL值。您也可以使用union all
和group by
执行此操作——假设表中没有重复的表:
SELECT G.FILTER1, G.FILTER2, T1.DATA1, T2.DATA1 as DATA2 FROM
(SELECT FILTER1, FILTER2
FROM TABLE1
UNION
SELECT FILTER1, FILTER2
FROM TABLE2
GROUP BY FILTER1, FILTER2) as G
LEFT JOIN TABLE1 as T1 ON T1.FILTER1 = G.FILTER1 AND T1.FILTER2 = G.FILTER2
LEFT JOIN TABLE2 as T2 ON T2.FILTER1 = G.FILTER1 AND T2.FILTER2 = G.FILTER2
select filter_1, filter_2, max(data_1) as data_1, max(data_2) as data_2
from ((select filter_1, filter_2, data_1, NULL as data_2
from table1
) union all
(select filter_1, filter_2, NULL, data_2
from table2
)
) t
group by filter_1, filter_2;
我将此作为替代方案。首先,(对我来说)有趣的是,union-all
/groupby
的行为与full-outer-join
的行为相同。更重要的是,如果您开始添加更多的表,那么完全外部联接
方法将变得很麻烦。将此方法扩展到更多表是很容易的。您也可以使用union all
和group by
来实现这一点——假设表中没有重复的表:
select filter_1, filter_2, max(data_1) as data_1, max(data_2) as data_2
from ((select filter_1, filter_2, data_1, NULL as data_2
from table1
) union all
(select filter_1, filter_2, NULL, data_2
from table2
)
) t
group by filter_1, filter_2;
我将此作为替代方案。首先,(对我来说)有趣的是,union-all
/groupby
的行为与full-outer-join
的行为相同。更重要的是,如果您开始添加更多的表,那么完全外部联接
方法将变得很麻烦。将此方法扩展到更多表很容易。是的,我忘记将TABLE1.FILTER1和TABLE2.FILTER1合并到一个列中。我回答得太快了,专注于“加入”部分,让我编辑我的答案。ISNULL不是非标准的SQL bahavior吗?@user1759572-操作说明SQL-SERVER和ISNULL在那里是完全正常的。@user1759572我认为这是非标准的,我不是100%确定。但是问题是标记为sql server,它比合并(相当长)要短,所以…是的,我忘记了将TABLE1.FILTER1和TABLE2.FILTER1合并到一个列中。我回答得太快了,专注于“加入”部分,让我编辑我的答案。ISNULL不是非标准的SQL bahavior吗?@user1759572-操作说明SQL-SERVER和ISNULL在那里是完全正常的。@user1759572我认为这是非标准的,我不是100%确定。但是问题是标记为sql server,它比(相当长的)合并要短,所以…请验证我的逻辑:如果我知道TABLE1包含所有筛选器组合,我可以使用左连接而不使用合并,我的查询速度会快得多。@MattAlexander-合并几乎不会影响性能。即使在对大量输出记录执行标量函数时,与连接本身相比,标量函数几乎总是微不足道的。但是,是的,在您的新示例中,您可以使用左连接,这可能有性能优势,具体取决于索引等。请验证我的逻辑:如果我知道表1包含所有过滤器组合,我可以使用左连接,而不使用合并,而且我的查询速度会快得多。@matt-COALESCE几乎不会影响性能。即使在对大量输出记录执行标量函数时,与连接本身相比,标量函数几乎总是微不足道的。但是,在您的新示例中,可以使用左连接,这可能有性能优势,具体取决于索引等。为什么这比完全外部连接更可取?这似乎是阅读量的两倍……没有偏好,只是另一种方式而已。就性能而言,它的性能不如完全外部连接。为什么这比完全外部连接更好?这似乎是阅读量的两倍……没有偏好,只是另一种方式而已。就性能而言,它的性能不如完全外部联接。是否不需要联合中的第一个SELECT来显式地将NULL强制转换为正确的数据类型?如果不是,SQL Server使用什么规则来确定用NULL初始化的字段的数据类型?是否不需要联合中的第一个SELECT来显式地将NULL强制转换为正确的数据类型?如果不是,SQL Server使用什么规则来确定用NULL初始化的字段的数据类型?