Застосування функції агрегату 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значення бітів у полі.)


2
@Adam Robinson: Очевидно,Operand data type bit is invalid for min operator.
Andomar

4
Не знаю про більш елегантний, але він трохи коротший. cast(min(SomeBitField+0) as bit)
Mikael Eriksson

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критеріями) в a CTEна початку запиту, тоді посилайтеся на це у CASEвисловлюваннях.


10
Існує три варіанти, bitякщо він може бути анульований.
Martin Smith

1
Якщо bitстовпець повністю складався зі NULLзначень, тоді MINповинен повернутися NULL.
Martin Smith

8
Напевно, я "менший" програміст, але я хотів би бачити повний приклад select 1 from ...підзапиту. Це не зовсім має сенс.
Ваккано

2
@Vaccano -SELECT 1 FROM Outertable WHERE bitfield=1
JNK

2
Оригінальне питання включало GROUP BY. Вам потрібно включити групу за критеріями до ДЕ.
Тмдіан,

156

Одним із варіантів є MIN(SomeBitField+0). Він добре читається, з меншим рівнем шуму (що я кваліфікую як елегантність).

Тим не менш, це більше хак, ніж CASEваріант. І я нічого не знаю про швидкість / ефективність.


@Ben, дякую, цей Алсон допоможе мені в моєму запиті SQL.
PatsonLeaner

@Ben, у вас є якась документація +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



6

Спробуйте наступне Примітка: Мінімум представляє А сукупна функція, Макс представляє Або сукупна функція

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 (boolean_column AS FLOAT)) OVER (...) AS BOOLEAN_AGGREGATE

Дайте нечітке логічне значення:

  • 1 вказують, що це все True;

  • 0 означає, що це все хибно;

  • значення між] 0..1 [вказує часткове збіг і може бути певним відсотком істини.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.