Not a big deal in this case, but I don't like generating hundreds of values when I need only 12 :-). I think code below does less work and also has no language dependencies:
DECLARE @year datetime
SET @year = GETDATE()
;WITH
cteDigits AS (
SELECT 0 AS digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL
SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
),
cteMonths AS (
SELECT [10s].digit * 10 + [1s].digit AS month#
FROM cteDigits [1s]
CROSS JOIN cteDigits [10s]
WHERE
[10s].digit * 10 + [1s].digit BETWEEN 1 AND 12
)
SELECT
first_day_of_month +
CASE WHEN DATEDIFF(DAY, 0, first_day_of_month) % 7 < 5 THEN 0
WHEN DATEDIFF(DAY, 0, first_day_of_month) % 7 = 5 THEN 2 ELSE 1 END
AS first_workday_of_month
FROM cteMonths
CROSS APPLY (
SELECT DATEADD(YEAR, DATEDIFF(YEAR, 0, @year), 0) AS first_day_of_year
) AS ca1
CROSS APPLY (
SELECT DATEADD(MONTH, month# - 1, first_day_of_year) AS first_day_of_month
) AS ca2
ORDER BY
first_workday_of_month
SQL DBA,SQL Server MVP(07, 08, 09) A socialist is someone who will give you the shirt off *someone else's* back.