Ok.. sorry for the delay...
@Mateen,
Scott is definitely on the right track. To make things even easier, I strongly recommend that you add the proverbial "Swiss Army Knife" of SQL to your database(s). It will also keep "Tally Overrun" accidents from happening.
You can find it at the article at the following link.
https://www.sqlservercentral.com/scripts/create-a-tally-function-fntally
If your DBA complains about functions, explain that it's a very high performance iTVF (inline Table Valued Function) that works as if the code for the function were inline like any of the other code.
After that, things of this nature become nearly trivial to solve.
WITH
cteDateLimits AS
(--==== Find the min/max DATEs (which are easier to work with) for each code.
SELECT code
,MinYYYYMM = MIN(CONVERT(DATE,CONVERT(CHAR(8),yearmonth*100+1),112))
,MaxYYYYMM = MAX(CONVERT(DATE,CONVERT(CHAR(8),yearmonth*100+1),112))
FROM @T
GROUP BY code
)
,cteDateRange AS
(--==== "DRY" out the formulas while calculating all yearmonth values for each code.
SELECT code
,yearmonth = CONVERT(INT,CONVERT(CHAR(6),DATEADD(mm,t.N,MinYYYYMM),112))
FROM cteDateLimits
CROSS APPLY dbo.fnTally(0,DATEDIFF(mm,MinYYYYMM,MaxYYYYMM)) t
)--==== Find the skipped dates for each code.
SELECT code
,OK = yearmonth
FROM cteDateRange drng
WHERE NOT EXISTS (SELECT * FROM @t t WHERE t.code = drng.code AND t.yearmonth = drng.yearmonth)
ORDER BY code, yearmonth
;
I also recommend that the first column in your table should actually be a CHAR(6) instead of a VARCHAR(6) because the latter takes an extra 2 bytes per row and that you should never store temporal data as INTs. In this case, use the DATE datatype and don't format them as YYYYMM until it's display/report time. Certainly there is no need to store a 6 digit INT as a BIGINT.
Oldest rule in the books... keep the data layer separate from the presentation layer. In most cases, it will make small miracles much easier to perform and usually a good bit faster because you'll only suffer one CONVERT.