Aplicar la función agregada MIN a un campo BIT

82

Quiero escribir la siguiente consulta:

SELECT   ..., MIN(SomeBitField), ...
FROM     ...
WHERE    ...
GROUP BY ...

El problema es que a SQL Server no le gusta, cuando quiero calcular el valor mínimo de un campo de bits , devuelve el error Operand data type bit is invalid for min operator.

Podría usar la siguiente solución:

SELECT   ..., CAST(MIN(CAST(SomeBitField AS INT)) AS BIT), ...
FROM     ...
WHERE    ...
GROUP BY ...

Pero, ¿hay algo más elegante? (Por ejemplo, puede haber una función agregada, que no conozco, y que evalúa la lógica andde los valores de bits en un campo).

pyon
fuente
2
@Adam Robinson: Obviamente,Operand data type bit is invalid for min operator.
Andomar
4
No sé si es más elegante pero es un poco más corto. cast(min(SomeBitField+0) as bit)
Mikael Eriksson
5
@Andomar: Obviamente, si ya conoce el problema, sí, pero otros con problemas similares pueden buscar en el mensaje de error , por lo que información como esa debe estar en la pregunta.
Adam Robinson

Respuestas:

33

Dado que solo hay dos opciones para BIT, simplemente use una declaración de caso:

SELECT CASE WHEN EXISTS (SELECT 1 FROM ....) THEN 1 ELSE 0 END AS 'MinBit'
FROM ...
WHERE ...

Esto tiene la ventaja de:

  • No forzar un escaneo de tabla (los índices en los BITcampos casi nunca se usan)
  • Cortocircuito DOS VECES (una vez EXISTSy otra vez para el CASE)

Es un poco más de código para escribir, pero no debería ser terrible. Si tiene varios valores para verificar, siempre puede encapsular su conjunto de resultados más grande (con todos los criterios JOINy FILTER) CTEal comienzo de la consulta, luego haga referencia a eso en las CASEdeclaraciones.

JNK
fuente
10
Hay tres opciones para bitsi es anulable.
Martin Smith
1
Si la bitcolumna constaba completamente de NULLvalores, MINdebería regresar NULL.
Martin Smith
8
Debo ser un programador "menor", pero me hubiera gustado ver un ejemplo completo de la select 1 from ...subconsulta. No tiene mucho sentido.
Vaccano
2
@Vaccano -SELECT 1 FROM Outertable WHERE bitfield=1
JNK
2
Sin embargo, la pregunta original incluía un GROUP BY. Debe incluir el grupo por criterios en el DÓNDE.
Tmdean
156

Una opción es MIN(SomeBitField+0). Se lee bien, con menos ruido (lo que yo calificaría de elegancia).

Dicho esto, es más hack-ish que la CASEopción. Y no sé nada sobre velocidad / eficiencia.

Ben Mosher
fuente
@Ben, muchas gracias, esto también me ayudó con mi consulta SQL.
PatsonLeaner
@Ben, ¿tienes alguna documentación de +0 ?, intenté buscarla pero no encontré nada, solo por referencias :)
Francisco Sevilla
1
@FranciscoSevilla Creo que se debe a la conversión de precedencia implícita: docs.microsoft.com/en-us/sql/t-sql/data-types/…
Ben Mosher
7

Esta consulta es la mejor solución:

SELECT CASE WHEN MIN(BitField+0) = 1 THEN 'True' ELSE 'False' END AS MyColumn
 FROM MyTable

Cuando agrega BitField + 0, automáticamente se convierte en int

Israel Margulies
fuente
7
select min(convert(int, somebitfield))

o si quieres mantener el resultado como poco

select convert(bit, min(convert(int, somebitfield)))
Vernard Sloggett
fuente
6

Pruebe la siguiente nota: función mínima de representación y agregación, función máxima de representación o agregación

SELECT   ..., MIN(case when SomeBitField=1 then 1 else 0 end), MIN(SomeBitField+0)...
FROM     ...
WHERE    ...
GROUP BY ...

mismo resultado

Waleed AK
fuente
5

Este pequeño fragmento de código siempre me ha funcionado como un encanto:

CONVERT(BIT, MIN(CONVERT(INT, BitField))) as BitField
Legión del Caos
fuente
2

AVG (CAST (boolean_column AS FLOAT)) OVER (...) AS BOOLEAN_AGGREGATE

Dar un booleano difuso:

  • Indico que todo eso es cierto;

  • 0 indica que todo es falso;

  • un valor entre] 0..1 [indica coincidencia parcial y puede ser un porcentaje de verdad.

usuario7370003
fuente