2010-12-14 14 views
10

Como parte de un agregado complejo quiero saber el nivel de bits suma de algunos datos, es decir, si tengo filas con valores 1,1,1,2,2,8 la suma es bit a bit 11. En este caso, los valores son todos potencias exactas de dos (bits individuales), por lo que puedo hackear agrupando y sumando sobre los grupos (obviamente este ejemplo es un poco torturado en comparación con la consulta real):la realización de una suma 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 

, pero ¿hay una manera limpia de realizar una suma bit a bit en [T] SQL?

+0

Marc, ¿Básicamente estás hablando de ORing todos esos valores? ¿O quiere decir eliminar primero los duplicados, luego agregar (sin embargo, no estoy seguro de que usaría el término en bits para eso)? – paxdiablo

+0

@paxdiablo ambos; a nivel de bit O sobre el conjunto sería idéntico al agregado único, ya que cada uno es una potencia absoluta de 2 –

Respuesta

18

Si todos sus valores de prueba son bits individuales como en su ejemplo (1, 2, 8), simplemente use SUM(DISTINCT col) en su consulta.

Espero que ayude.

(para la referencia: http://msdn.microsoft.com/en-us/library/ms187810.aspx)

+0

Hahaha. ¡gran respuesta! –

+0

Agradable; Me gusta ese enfoque; funciona maravillosamente –

0

Tienes el operador | que realiza bit a bit o para 2 operandos. Es posible resolver su problema usando un cursor y este operador.

Editar sí Mezclé y y o, arreglado.

3

Es un poco intrincado, pero esto hace lo que está buscando (tenga en cuenta que he incluido bit de hasta 128, puede que necesite ir más alto, o puede que no necesite ir más allá de 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 

que obviamente se puede convertir a un UDF si así lo desea.

+0

Estoy tratando de averiguar cómo convertir esto a un UDF. Puedes profundizar sobre eso? – Gabe

0

Para los bits individuales de la SUM (col DISTINCT) es la mejor respuesta, pero para múltiples bits como 3 (= 1 | 2) esto no funciona y la mejor y más rápida respuesta sería como esta:

SUM SELECT (X.Text DISTINCT & TB) DE transversal X se unen (los valores (1), (2), (4), (8), (16), (32), (64), (128), (256), (512)) T (B)