Применение агрегатной функции MIN к BIT-полю

82

Я хочу написать такой запрос:

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

Проблема в том, что SQL Server не любит, когда я хочу вычислить минимальное значение битового поля, он возвращает ошибку Operand data type bit is invalid for min operator.

Я мог бы использовать следующий обходной путь:

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

Но есть ли что-нибудь более элегантное? (Например, может быть агрегатная функция, о которой я не знаю, и которая оценивает логические andзначения битов в поле.)

Pyon
источник
2
@Adam Robinson: Очевидно,Operand data type bit is invalid for min operator.
Andomar
4
Не знаю, как элегантнее, но он немного короче. cast(min(SomeBitField+0) as bit)
Микаэль Эрикссон,
5
@Andomar: Очевидно, что, если вы уже знаете проблему, да, но другие люди с похожими проблемами могут искать по сообщению об ошибке , поэтому такая информация должна быть в вопросе.
Адам Робинсон,

Ответы:

33

Поскольку есть только два варианта BIT, просто используйте оператор case:

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

Это имеет преимущество:

  • Отсутствие принудительного сканирования таблицы (индексы в BITполях практически никогда не используются)
  • Короткое замыкание ДВАЖДЫ (один раз EXISTSи снова для CASE)

Это еще немного кода, но он не должен быть ужасным. Если у вас есть несколько значений , чтобы проверить , вы всегда можете инкапсулировать больший набор результатов (со всеми JOINи FILTERкритериями) в CTEначале запроса, то ссылки , что в CASEотчетности.

JNK
источник
10
Есть три варианта, bitесли он допускает значение NULL.
Мартин Смит
1
Если bitстолбец полностью состоит из NULLзначений, он MINдолжен вернуться NULL.
Мартин Смит
8
Я должен быть программистом «на меньшем уровне», но я хотел бы увидеть полный пример select 1 from ...подзапроса. Это не совсем понятно.
Vaccano,
2
@Vaccano -SELECT 1 FROM Outertable WHERE bitfield=1
JNK
2
Однако исходный вопрос включал GROUP BY. Вам нужно включить группу по критериям в ГДЕ.
Tmdean
156

Один вариант есть MIN(SomeBitField+0). Он хорошо читается, с меньшим шумом (что я бы назвал элегантностью).

Тем не менее, это более хакерский CASEвариант, чем вариант. И я ничего не знаю о скорости / эффективности.

Бен Мошер
источник
@Ben, Большое спасибо, это тоже помогло мне с моим SQL-запросом.
PatsonLeaner 01
@ Бен, у вас есть документация по +0 ?, Пытался найти, но ничего не нашел, просто для справки :)
Франсиско Севилья,
1
@FranciscoSevilla Я считаю, что это из-за неявного преобразования приоритета: docs.microsoft.com/en-us/sql/t-sql/data-types/…
Бен Мошер
7

Этот запрос - лучшее решение:

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

Когда вы добавляете BitField + 0, он автоматически становится как int

Израиль Маргулис
источник
7
select min(convert(int, somebitfield))

или если вы хотите сохранить результат как бит

select convert(bit, min(convert(int, somebitfield)))
Вернард Слоггетт
источник
6

Попробуйте следующее примечание: Min представляет и агрегатную функцию, Max представляет или агрегатную функцию

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

тот же результат

Валид АК
источник
5

Этот небольшой фрагмент кода всегда работал со мной как шарм:

CONVERT(BIT, MIN(CONVERT(INT, BitField))) as BitField
Легион Хаоса
источник
2

AVG (CAST (логический_столбец AS FLOAT)) OVER (...) AS BOOLEAN_AGGREGATE

Задайте нечеткое логическое значение:

  • 1 означает, что все верно;

  • 0 означает, что все это ложь;

  • значение между] 0..1 [указывает на частичное совпадение и может составлять некоторый процент истинности.

user7370003
источник