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).


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.


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, 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


7
select min(convert(int, somebitfield))

o si quieres mantener el resultado como poco

select convert(bit, min(convert(int, somebitfield)))

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


5

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

CONVERT(BIT, MIN(CONVERT(INT, BitField))) as BitField

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.