Declare @OrigTab Table(Part varchar(30), qty int)
insert into @OrigTab
select 'X51','3' union
select 'A5','1' union
select '123','2' union
select '054','5'
select * from @OrigTab ORDER BY 1 DESC
;WITH
-- Make an inline tally table (CTE)
E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), --10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
Tally(N) AS (SELECT 1 FROM E2 a, E2 b)
-- use the tally table as a source of rows
SELECT
TAG = 'PNM-'+RIGHT('0'+CAST(ROW_NUMBER() OVER(ORDER BY Part DESC) AS VARCHAR(2)),2),
o.Part,
o.qty
FROM @OrigTab o
CROSS APPLY (SELECT TOP(o.qty) N FROM Tally) x
ORDER BY Part DESC
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