2013-05-06 4 views
7

Ich habe einen Bitmask-Wert als int in SQL gespeichert. Ich möchte diesen Wert in eine kommagetrennte Liste der im Bitmaskenwert enthaltenen Werte umwandeln.In SQL, wie kann ich die Werte in einem Bitmask insgesamt in eine durch Kommas getrennte Zeichenfolge teilen

So zum Beispiel könnten die Ergebnisse wie so aussehen:

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

Gibt es eine Möglichkeit, dies in einer SQL-Anweisung zu erreichen?

Dies ist SQL Server 2008.

+1

Diese Frage keine Forschungsanstrengungen nicht zeigen. Es ist wichtig, ** deine Hausaufgaben zu machen **. Sagen Sie uns, was Sie gefunden haben und *** warum *** es nicht Ihren Bedürfnissen entspricht. Dies zeigt, dass Sie sich die Zeit genommen haben, sich selbst zu helfen, es rettet uns davor, offensichtliche Antworten zu wiederholen, und vor allem hilft es Ihnen, eine spezifischere und relevantere Antwort zu bekommen. [FAQ] (http://stackoverflow.com/questions/how-to-ask). – Kermit

+3

Nur ein FYI, Sie missbrauchen wirklich Ihre RDBMS. Datenbanken sollen wirklich gut mit Fremdschlüsseln funktionieren. Ich hoffe, Sie hatten einige ziemlich spezielle Anforderungen, bevor Sie Ihrem Datensatz eine Bitmaske hinzugefügt haben, anstatt die Daten ordnungsgemäß zu normalisieren und eine typische Junction-Tabelle zu verwenden. – meagar

+0

Ich stimme dir völlig zu @meagar. In meinem Fall habe ich einige Legacy-Daten (den bitMaskValue), die ich gerade zu normalisieren versuche und an eine andere Quelle weiterleiten möchte, die kommagetrennte Werte verwendet. Ich dachte, es wäre ein interessantes Puzzle und da ich keine sql-only-Lösungen über Google oder SO fand, habe ich mich gefragt, welche guten Lösungen die Leute haben könnten. – Jimtronic

Antwort

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

Danke. Ich habe dafür eine Funktion erstellt und es hat gut funktioniert. Ich habe die Ausgabe von 'str (@ bit, 2,1)' in 'str (power (2, @ bit), 2,1)' geändert, um den Anforderungen zu entsprechen. – Jimtronic

+0

BTW, ich stimme völlig mit @ magers Kommentar zu Ihrer Frage überein. Dies ist keine angemessene/gute Verwendung eines Datenbankservers ... –

3

Diese Arbeit sollte:

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

Genau das habe ich gesucht! Ich danke dir sehr. – 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 
Verwandte Themen