我有一个SQL查询在另一个表上执行LEFT JOIN,然后输出可以耦合到指定表中的所有结果。然后我有第二个SQL查询再次执行LEFT JOIN,然后输出无法耦合到指定表的结果。在代码中,这类似于:
INSERT INTO coupledrecords
SELECT b.col1, b.col2... s.col1, s.col2... FROM bigtable AS b
LEFT JOIN smallertable AS s
ON criterium
WHERE s.col1 IS NOT NULL
INSERT INTO notcoupledrecords
SELECT b.col1, b.col2... bigtable AS b
LEFT JOIN smallertable AS s
ON criterium
WHERE s.col1 IS NULL
我的问题:我现在必须执行两次JOIN,以达到我想要的效果。我觉得这是它的两倍慢。这是真的,如果是的话,有没有办法更有效地做到这一点?
答案 0 :(得分:4)
如果您将不同的结果插入2个不同的表中,则需要2个不同的查询。
我唯一建议的是,“coupledrecords”查询可以只是一个INNER JOIN:
INSERT INTO coupledrecords
SELECT b.col1, b.col2... s.col1, s.col2... FROM bigtable AS b
INNER JOIN smallertable AS s
ON criterium
如果您要插入SAME表,并带有一个字段来指示它是否是匹配的记录,那么您可以将其作为一个查询进行。
答案 1 :(得分:3)
底线是,您需要2个查询,因为您要插入2个不同的表。如果你只有一个表而不是coupledrecords和notcoupledrecords,那么你可以在1个查询中完成。 :)
答案 2 :(得分:3)
我认为你能做到的一种方法是创建一个分区视图,在列上指示耦合/未耦合的检查约束。然后插入视图,让SQL Server找出目标表。并没有暗示你这样做只是因为我认为它是一种可能性!
INSERT INTO coupledrecordsView
SELECT case WHEN s.col1 IS NULL THEN 1 ELSE 0 END AS IsCoupled,
b.col1, b.col2... s.col1, s.col2... FROM bigtable AS b
LEFT JOIN smallertable AS s
ON criterium
答案 3 :(得分:2)
如果您可以更改coupledrecords
和notcoupledrecords
的聚簇索引以包含smalltable中的一列(包括在每个聚簇索引的末尾添加计算位列,仅用于此目的 - 请参阅@Martin Smith上面的答案详细说明)然后你可以使用Partitioned View作为插入。这很容易。
如果不可能,那么您也可以尝试非分区视图解决方案。见下文 - 它涉及更多。
在不知道数据如何分布的情况下(例如行大小,可空列与不可空列的数量,耦合与非耦合的比率),很难推荐一般解决方案,但在大多数情况下可能运行良好的一种解决方案是使用视图在单个“maybecoupled
”表格上模拟耦合和非耦合表。使用视图意味着您不必更改现有的查询代码(插入除外)。
乍一看这看起来非常低效,但请记住空值占用零存储空间,并且使用适当的索引,SQL不会浪费太多过滤掉“其他视图”行。
以下是它的工作原理:
maybecoupled
)smalltable
获得的一个列上有一个索引(理想情况下是聚簇索引,但非聚簇也可以)。我们假设这是indexedcol1
coupledrecords
和notcoupledrecords
,其定义为SELECT col1, ... FROM maybecoupled WHERE indexedcol1 IS NULL
和SELECT col1, ... FROM maybecoupled WHERE indexedcol1 IS NOT NULL
。以下解决方案无效的情况如下:
bigtable
中有很多不可为空的列,或者您的行数非常少。那么所有那些非耦合行的空间开销可能会受到伤害。 (nulls不占用空间,但不可为空的列。)警告:你肯定想测试任何基于视图的解决方案的性能,以确保它不会让事情变得更糟 - SQL通常擅长选择好的查询计划,但并非总是如此。测试,测试,测试!
答案 4 :(得分:0)
你基本上将数据改为两个。一旦你完成了它,一旦你有一组关键记录,你应该只从那里做 NOT IN
INSERT INTO notcoupledrecords
SELECT b.col1, b.col2... bigtable AS b
WHERE some_col not in (select some_col from coupledrecords)