Thanks to Lynn & Sean for the formatted query:
-- code rewrites are iterative in nature. You make a change or two,
-- test thoroughly, amend if necessary, then make another change.
-- Here's two changes (with no data to test against):
-- 1: use of table aliases and USE to eliminate unnecessary characters
-- and 2: a rewrite of the subquery in the WHERE clause.
USE [Build1]
SELECT DISTINCT TYPE_ID
INTO #TypeIDNoChild
FROM TBL_TYPE_DEF
WHERE TYPE_ID NOT IN (SELECT CHILD_TYPE FROM TBL_RELATIONSHIPS_ALLOWED)
SELECT
td.TYPE_NAME
,i.DOC_NAME
,i.DOC
,i.SEC
,i.VER
,r.JUSTIFICATION
FROM TBL_INSTANCES i
INNER JOIN TBL_TYPE_DEF td
ON i.TYPE_ID = td.TYPE_ID
LEFT JOIN TBL_RELATIONSHIPS r
ON i.DOC = r.PARENT_DOC
AND i.SEC = r.PARENT_SEC
AND i.VER = r.PARENT_VER
WHERE NOT EXISTS (
SELECT 1
FROM TBL_RELATIONSHIPS ri
INNER JOIN TBL_INSTANCES ii
ON ii.DOC = ri.PARENT_DOC
AND ii.SEC = ri.PARENT_SEC
AND ii.VER = ri.PARENT_VER -- nullable
AND ii.TYPE_ID IN (SELECT TYPE_ID FROM #TypeIDNoChild)
WHERE ri.CHILD_DOC IS NOT NULL
AND ri.PARENT_DOC = i.DOC
AND ri.PARENT_SEC = i.SEC
AND ri.PARENT_VER = i.VER
)
AND i.TYPE_ID IN (SELECT TYPE_ID FROM #TypeIDNoChild)
ORDER BY td.TYPE_ID
,i.DOC
,i.SEC
,i.VER
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden