2010-12-14 18 views
10

Come parte di un aggregato complesso voglio sapere il bit a bit somma di alcuni dati, vale a dire se ho righe con valori 1,1,1,2,2,8 la bit somma è 11. In questo caso i valori sono tutti potenze esatte di due (bit singoli), quindi posso aggirarlo raggruppando e sommando i gruppi (ovviamente questo esempio è un po 'torturato rispetto alla query reale):l'esecuzione di una somma bit a bit

select SUM(y.test) 
from (
    select x.test 
    from (-- garbage test data 
     select 1 as [test] 
     union all select 1 
     union all select 1 
     union all select 2 
     union all select 2 
     union all select 8) x 
group by x.test) y 

ma c'è un modo pulito per eseguire una somma bit a bit in [T] SQL?

+0

Marc, stai fondamentalmente parlando di OR tutti questi valori? O vuoi dire rimuovere prima i duplicati, poi aggiungere (non sono sicuro che userei il termine bitwise per quello)? – paxdiablo

+0

@paxdiablo entrambi; OR bit a bit sul set sarebbe identico all'aggiunta univoca, poiché ognuno è una potenza assoluta di 2 –

risposta

18

Se tutti i valori di test sono bit singoli come nell'esempio (1, 2, 8), utilizzare semplicemente SUM(DISTINCT col) nella query.

Spero che questo aiuti.

(per riferimento: http://msdn.microsoft.com/en-us/library/ms187810.aspx)

+0

Hahaha. Bella risposta! –

+0

Nizza; Mi piace questo approccio; funziona magnificamente –

0

Hai l'operatore | che esegue bit per bit o per 2 operandi. È possibile risolvere il problema usando un cursore e questo operatore.

Modifica Sì, ho mescolato e e o, risolto.

3

È un po 'contorto ma questo è quello che stai cercando (nota che i bit inclusi sono compresi tra 128 e 128, potrebbe essere necessario andare più in alto o non avere bisogno di andare oltre 8).

with data(i) 
AS 
(
    select 1 
     union all select 1 
     union all select 1 
     union all select 2 
     union all select 2 
     union all select 8 
) 
SELECT MAX(i & 1) + 
MAX(i & 2) + 
MAX(i & 4) + 
MAX(i & 8) + 
MAX(i & 16) + 
MAX(i & 32) + 
MAX(i & 64) + 
MAX(i & 128) 
from data 

che può ovviamente essere convertito in UDF se lo si desidera.

+0

Sto cercando di capire come convertire questo in un UDF. Puoi approfondire questo? – Gabe

0

Per singoli bit SUM (col DISTINCT) è migliore risposta, ma per una molteplicità di bit come 3 (= 1 | 2) non funziona e migliore e più rapida risposta sarebbe in questo modo:

SELECT SUM (DISTINCT X.Text & TB) DA X trasversale join (valori (1), (2), (4), (8), (16), (32), (64), (128), (256), (512)) T (B)