BIT COUNT: примеры (SQL)

Реализация подсчета битов BIT_COUNT в Microsoft SQL Server
Раздел: Битовые функции, Битовые
BIT_COUNT(expression integer): int

Описание функции BIT_COUNT в MS SQL

В Microsoft SQL Server не существует встроенной функции с именем BIT_COUNT. Однако необходимость в подсчете количества установленных битов (единиц) в двоичном представлении целого числа может быть реализована через пользовательскую функцию. Такая функция полезна при работе с битовыми масками, флагами или при выполнении низкоуровневых оптимизаций, где требуется анализ отдельных бит данных.

Пользовательскую функцию можно создать для обработки целочисленных типов данных: INT, BIGINT, SMALLINT, TINYINT. Функция принимает один аргумент - числовое значение, и возвращает целое число, соответствующее количеству битов, равных 1. Реализация часто основана на алгоритме Кернигана, который эффективно подсчитывает установленные биты, последовательно сбрасывая младший установленный бит.

Примеры использования функции подсчета битов

Ниже представлен код создания пользовательской функции и примеры ее вызова.

CREATE FUNCTION dbo.BitCount (@value BIGINT)
RETURNS INT
AS
BEGIN
    DECLARE @count INT = 0
    WHILE @value != 0
    BEGIN
        SET @value = @value & (@value - 1)
        SET @count = @count + 1
    END
    RETURN @count
END
GO

Примеры вызова функции:

SELECT dbo.BitCount(0) AS BitCountZero;
-- Число 0 в двоичном виде: 0
BitCountZero
0
SELECT dbo.BitCount(15) AS BitCountFifteen;
-- Число 15 в двоичном виде: 1111
BitCountFifteen
4
SELECT dbo.BitCount(255) AS BitCount255;
-- Число 255 в двоичном виде: 11111111
BitCount255
8
SELECT dbo.BitCount(-1) AS BitCountMinusOne;
-- Число -1 для BIGINT: все 64 бита равны 1
BitCountMinusOne
64

Похожие функции и методы в MS SQL

Прямого аналога BIT_COUNT в T-SQL нет, но существуют другие битовые операции:

  • & (AND), | (OR), ^ (XOR) - побитовые операторы для выполнения логических операций.
  • ~ (NOT) - побитовое отрицание.
  • << (LEFT SHIFT), >> (RIGHT SHIFT) - операторы битового сдвига, которые могут быть использованы для анализа позиций битов.

Для подсчета битов иногда используют предварительно рассчитанную таблицу соответствия (lookup table) на 256 значений (от 0 до 255), что может быть быстрее для больших объемов данных, чем итеративный алгоритм.

Аналоги функции в других СУБД и языках

Во многих других системах существуют встроенные функции для подсчета битов.

MySQL: Функция BIT_COUNT() является встроенной.

SELECT BIT_COUNT(15);
4

PostgreSQL: Можно использовать функцию popcount, часто доступную через расширение или операторы. Например, с использованием агрегата bit_and.

SELECT length(replace((15::bit(8))::text, '0', '')); -- Самодельный способ
4

Oracle: Стандартной функции нет, но можно использовать функцию UTL_RAW.popcnt или написать PL/SQL код.

SELECT UTL_RAW.POPCOUNT(UTL_RAW.CAST_FROM_BINARY_INTEGER(15)) FROM dual;
4

SQLite: Встроенной функции нет, требуется создание пользовательской функции на C или использование выражений CASE.

Язык программирования C++: В стандартной библиотеке есть функция std::bitset::count().

#include <bitset>
std::bitset<8> bits(15);
int count = bits.count(); // =4

Типичные ошибки при реализации подсчета битов

Основные ошибки связаны с обработкой отрицательных чисел и типами данных.

1. Ошибка с бесконечным циклом при использовании неподписанных типов: В SQL Server нет неподписанных целых типов, поэтому для отрицательных значений алгоритм Кернигана работает корректно, так как работает с двоичным дополнением.

2. Неправильный результат при передаче NULL: Функция должна обрабатывать NULL.

SELECT dbo.BitCount(NULL); -- Вернет NULL, если не обработано
NULL

3. Потеря точности при передаче нецелочисленного значения: Необходимо явное приведение типов.

SELECT dbo.BitCount(CAST(15.7 AS INT)); -- Явное приведение

Изменения в последних версиях MS SQL

На момент написания статьи в Microsoft SQL Server 2022 и более ранних версиях встроенная функция BIT COUNT не была добавлена. Функциональность по-прежнему требует реализации пользовательскими средствами. В обновлениях ядра SQL Server иногда добавляются новые системные функции, но информация о планах по включению BIT COUNT отсутствует.

Расширенные примеры использования подсчета битов

1. Анализ битовых флагов в столбце: Предположим, есть столбец с битовой маской, где каждый бит представляет наличие определенного атрибута. Можно подсчитать, сколько атрибутов активно для каждой записи.

Пример sql
CREATE TABLE Items (Id INT, Flags INT);
INSERT INTO Items VALUES (1, 5), (2, 3), (3, 0); -- 5=0101, 3=0011

SELECT Id, Flags, dbo.BitCount(Flags) AS ActiveAttributes
FROM Items;
Id  Flags  ActiveAttributes
1   5      2
2   3      2
3   0      0

2. Проверка на степень двойки: Число является степенью двойки, если количество установленных битов равно 1.

Пример sql
SELECT Number,
       CASE WHEN dbo.BitCount(Number) = 1 THEN 'Да' ELSE 'Нет' END AS IsPowerOfTwo
FROM (VALUES (1), (2), (3), (4), (8)) AS T(Number);
Number  IsPowerOfTwo
1       Да
2       Да
3       Нет
4       Да
8       Да

3. Оптимизированная табличная функция для быстрого подсчета: Использование заранее вычисленной таблицы на 256 значений для байта.

Пример sql
CREATE TABLE BitCountLUT (Value TINYINT PRIMARY KEY, BitCount TINYINT);
-- Заполнить таблицу значениями от 0 до 255 и количеством битов.
-- Затем функция может разбить число на байты и суммировать результаты.

4. Подсчет битов в шестнадцатеричной строке: Преобразование строки в число и подсчет.

Пример sql
SELECT dbo.BitCount(CAST(0xFF AS INT)) AS BitCountHex;
BitCountHex
8

MS SQL BIT_COUNT function comments

En
BIT COUNT Returns the number of bits that are set in the argument