2013-05-06 22 views
7

Ho un valore di maschera di bit memorizzato come int in sql. Mi piacerebbe trasformare quel valore in un elenco separato da virgole dei valori contenuti nel valore della maschera di bit.In SQL, come posso dividere i valori in un totale di maschera di bit in una stringa delimitata da virgole

Così, per esempio, i risultati potrebbero sembrare così:

id name  bitMaskValue values 
---------------------------------------- 
1 Bob  5    1,4 
2 Mary  13    1,4,8 
3 Stan  11    1,2,8 

C'è un modo per ottenere questo risultato in una dichiarazione di sql?

Si tratta di SQL Server 2008.

+1

Questa domanda non mostra alcuna attività di ricerca. È importante ** fare i compiti **. Dicci cosa hai trovato e *** perché *** non ha soddisfatto le tue esigenze. Questo dimostra che ti sei preso del tempo per cercare di aiutare te stesso, ci salva dal ribadire risposte ovvie e soprattutto ti aiuta a ottenere una risposta più specifica e pertinente. [FAQ] (http://stackoverflow.com/questions/how-to-ask). – Kermit

+3

Solo una FYI, stai davvero abusando del tuo RDBMS. I database devono funzionare * molto bene * con chiavi esterne. Spero che abbiate dei requisiti piuttosto specifici prima di aggiungere una maschera di bit al vostro record, piuttosto che normalizzare correttamente i dati e utilizzare una tabella di giunzione tipica. – meagar

+0

Sono completamente d'accordo con te @meagar. Nel mio caso, ho alcuni dati legacy (il bitMaskValue) che sto solo cercando di normalizzare e inviare ad un'altra fonte che prende valori delimitati da virgole. Ho pensato che fosse un puzzle interessante e dal momento che non stavo cercando soluzioni SQL solo tramite google o SO, mi sono chiesto quali buone soluzioni potrebbero avere le persone. – Jimtronic

risposta

1
declare @I integer = 2117 

Declare @v varChar(32) = '' 
Declare @Bit tinyInt = 0 
while @I > 0 Begin 
Set @v += case @I %2 WHen 1 Then str(@bit,2,1) + ',' else '' End 
Set @Bit += 1 
Set @i /= 2 
End 
Select case When len(@v) > 0 Then left(@v, len(@v) -1) else '' End 
+0

Grazie. Ho creato una funzione per questo e ha funzionato bene. Ho cambiato l'output da 'str (@ bit, 2,1)' a 'str (power (2, @ bit), 2,1)' per abbinare ciò di cui avevo bisogno. – Jimtronic

+0

btw, sono totalmente d'accordo con il commento di @ meager alla tua domanda. Questo non è un appropriato/buon uso di un server di database ... –

3

Questo dovrebbe funzionare:

SELECT id, name, bitMaskValue, 
    SUBSTRING(
      CASE WHEN bitMaskValue & 1 = 1 THEN ',1' ELSE '' END 
      + CASE WHEN bitMaskValue & 2 = 2 THEN ',2' ELSE '' END 
      + CASE WHEN bitMaskValue & 4 = 4 THEN ',4' ELSE '' END 
      + CASE WHEN bitMaskValue & 8 = 8 THEN ',8' ELSE '' END 
     , 2, 64) As [values] 
FROM yourTable 
+0

Questo è esattamente quello che stavo cercando! Grazie mille. – CowboyBebop

1

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 
Problemi correlati