First step (excuse the pun) is to generate a list of all the possible steps for each barcode. This query will generate a Table variable containing steps 1 to 5 for each of the barcodes in your sample:
DECLARE @AllSteps TABLE (step int, barcode bigint)
;with CTE as
(
select 1 as num, barcode from Working_Steps
UNION ALL
select CTE.num + 1 , Barcode
from CTE where num < 5
)
INSERT INTO @AllSteps
select DISTINCT * from CTE
You can then use that table variable to LEFT OUTER JOIN to table Working_Steps like this
SELECT O.Barcode, A.step, WS.idWorkingStep
FROM Orders O
INNER JOIN @AllSteps A ON O.Barcode = A.BarCode
LEFT OUTER JOIN Working_Steps WS ON WS.Barcode = O.Barcode AND WS.idWorkingStep=A.step
group by O.Barcode, A.step, WS.idWorkingStep
to get the following results (based on your sample in the question)
barcode step idWorkingStep
184512 1 1
184512 2 2
184512 3 NULL
184512 4 4
184512 5 5
184752 1 NULL
184752 2 NULL
184752 3 NULL
184752 4 4
184752 5 NULL
184764 1 NULL
184764 2 2
184764 3 3
184764 4 NULL
184764 5 NULL
You can then use a simple PIVOT to get the data into the format you want
SELECT * FROM
(
SELECT O.Barcode, A.step, WS.idWorkingStep
FROM Orders O
INNER JOIN @AllSteps A ON O.Barcode = A.BarCode
LEFT OUTER JOIN Working_Steps WS ON WS.Barcode = O.Barcode AND WS.idWorkingStep=A.step
group by O.Barcode, A.step, WS.idWorkingStep
) AS psource
PIVOT
(
COUNT(idWorkingStep) FOR step in ([1],[2],[3],[4],[5])
) AS pvt
Which gave me the following results
barcode 1 2 3 4 5
184512 1 1 0 1 1
184752 0 0 0 1 0
184764 0 1 1 0 0
[EDIT]
OP has clarified the requirement - any gaps in the sequence earlier than the maximum step achieved can be assumed to have been done. This adjustment to the query will achieve that (incorporating @RichardDeeming's suggestion too)
DECLARE @AllSteps TABLE (step int, barcode bigint)
INSERT INTO @AllSteps
SELECT T.num, S.barcode FROM Working_Steps As S
CROSS APPLY (VALUES (1), (2), (3), (4), (5)) As T (num)
SELECT Barcode, [1],[2],[3],[4],[5] FROM
(
SELECT O.Barcode, A.step, T.MaxPer,
CASE WHEN A.step < T.MaxPer THEN A.step
ELSE NULL END AS idWorkingStep
FROM Orders O
INNER JOIN @AllSteps A ON O.Barcode = A.BarCode
INNER JOIN (SELECT MAX(idWorkingStep) as MaxPer, Barcode FROM Working_Steps GROUP BY Barcode) T ON O.Barcode=T.Barcode
LEFT OUTER JOIN Working_Steps WS ON WS.Barcode = O.Barcode AND WS.idWorkingStep=A.step
group by O.Barcode, A.step, t.MaxPer, WS.idWorkingStep
) AS psource
PIVOT
(
COUNT(idWorkingStep) FOR step in ([1],[2],[3],[4],[5])
) AS pvt
ORDER BY Barcode
Which yields the results
barcode 1 2 3 4 5
184512 1 1 1 1 1
184752 1 1 1 1 0
184764 1 1 1 0 0
[EDIT 2]
Given that all steps up to the maximum recorded can be assumed to have been actioned then all we are really interested in is the maximum step recorded per barcode. So there is no need for the PIVOT at all - the same results can be generated by the following:
DECLARE @MaxSteps TABLE(MaxPer int, barcode bigint)
INSERT INTO @MaxSteps
SELECT MAX(idWorkingStep) as MaxPer, Barcode FROM Working_Steps GROUP BY Barcode
SELECT O.Barcode,
[1] = CASE WHEN M.MaxPer >= 1 THEN 1 ELSE 0 END,
[2] = CASE WHEN M.MaxPer >= 2 THEN 1 ELSE 0 END,
[3] = CASE WHEN M.MaxPer >= 3 THEN 1 ELSE 0 END,
[4] = CASE WHEN M.MaxPer >= 4 THEN 1 ELSE 0 END,
[5] = CASE WHEN M.MaxPer >=5 THEN 1 ELSE 0 END
FROM Orders O
LEFT OUTER JOIN @MaxSteps M ON O.Barcode = M.Barcode