【发布时间】:2021-10-10 00:02:00
【问题描述】:
样本数据:
DECLARE @Parent TABLE
(
[Id] INT
, [Misc_Val] VARCHAR(5)
) ;
DECLARE @Children TABLE
(
[Id] INT
, [P_ID] INT
) ;
INSERT INTO @Parent
VALUES
( 1, 'One' )
, ( 2, 'Two' )
, ( 3, 'Three' )
, ( 5, 'Four' ) ;
INSERT INTO @Children
VALUES
( 10, 1 )
, ( 11, 1 )
, ( 21, 2 )
, ( 23, 2 )
, ( 30, 3 )
, ( 40, 4 ) ;
目标: 为了高效输出三个字段( [Id] 和 [IsChild]、[Misc_Val] )。使用 [IsChild] = 0 输出 @Parent 表中的所有记录,并使用 [IsChild] = 1 输出 @Child 表 (@Parent.Id = @Children.P_Id) 中的所有 MATCHING 记录。
预期输出
Id IsChild Misc_Val
1 0 One
2 0 Two
3 0 Three
5 0 Four
10 1 One
11 1 One
21 1 Two
23 1 Two
30 1 Three
我的尝试:
SELECT [P].[Id]
, 0 AS [IsChild]
, [P].[Misc_Val]
FROM @Parent AS [P]
UNION ALL
SELECT [C].[Id]
, 1
, [P].[Misc_Val]
FROM @Parent AS [P]
JOIN @Children AS [C]
ON [C].[P_ID] = [P].[Id] ;
还有比使用 UNION ALL 更好的方法吗? @Parent 和 @Children 表非常大,因此我试图避免两次查询 @Parent 表。
更新:下面的答案让我意识到在使用模拟数据创建帖子时我错过了一些东西。不管在最终输出中,我们确实需要来自@Parent 表的一些额外数据。
【问题讨论】:
-
您有性能问题吗?因为如果不是...不要尝试预先优化它。
UNION ALL是解决此问题的正确方法,因为您将数据存储在 2 个表中(通常您会使用同一个表,引用自身)。 -
不幸的是,由于两个表中的行数都非常多,再次查询@Parent 表对系统来说是一个很大的问题。
-
这是一个写得很好的问题,但是对于性能问题,您应该始终使用Paste The Plan 发布实际查询(而不是您的模拟查询)的执行计划。您也不应该假设您知道提高性能的最佳方法(在这种情况下删除
union all),因为这可能不是解决方案。你的问题应该是,我怎样才能提高这个查询的性能。 -
对我来说有点像左外连接。如果有帮助,UNION 会消除重复项,而 UNION ALL 则不会
-
@DaleK 我已经多次遇到过这种情况,这让我很恼火,SQL 中没有简单的方法来表达它。
CROSS APPLY在我的回答中并不总是有效的,特别是如果子表没有很好的索引。我希望有一个OUTER WITH INNER JOIN。
标签: sql sql-server tsql optimization sql-server-2016