Reputation: 2186
Sample Data:
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 ) ;
Goal: To efficiently output three fields ( [Id] and [IsChild], [Misc_Val] ). Output all records from @Parent table with [IsChild] = 0 and output all MATCHING records from @Child table (@Parent.Id = @Children.P_Id) with [IsChild] = 1.
Expected Output
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
My try:
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] ;
Is there a better way to do this than using UNION ALL? @Parent and @Children tables are quite big and so am trying to avoid querying the @Parent table twice.
UPDATE: The below answer made me realized something I missed out when creating the post with mocked data. We do need some additional data from @Parent table regardless in the final output.
Upvotes: 0
Views: 122
Reputation: 71593
You can use CROSS APPLY
to add the child table to the parent table.
This may or may not be faster, it can depend on indexing and so forth. You need to check the query plan.
SELECT v.Id
, v.IsChild
, P.Misc_Val
FROM @Parent AS P
CROSS APPLY (
SELECT
P.Id,
0 AS IsChild
UNION ALL
SELECT
C.Id,
1
FROM @Children AS C
WHERE C.P_ID = P.Id
) v;
Note that the first SELECT
in the apply has no FROM
and therefore does not do any table access.
Upvotes: 3