CTE + XPATH way
:
set nocount on
declare @t as table(id int, name varchar(100), bitMaskValue int)
insert into @t(id, name, bitMaskValue) values(1,'Bob',5)
insert into @t(id, name, bitMaskValue) values(2,'Mary',13)
insert into @t(id, name, bitMaskValue) values(3,'Stan',11)
;with cte(num) as
(
select 1
union all
select num*2
from cte
)
select
id,
name,
bitMaskValue,
stuff((
select cast((
select isBitSet
from
(
select top 31 num,
case
when bitMaskValue & num = num then ',' + cast(num as varchar(10))
else null
end isBitSet
from cte
) tmp
where isBitSet is not null
for xml path('')) as xml).value('.', 'VARCHAR(max)')
), 1, 1, '') bitSet
from @t