2012-01-27 4 views
3

У меня есть таблица sqlite, когда в каждой таблице есть поле, которое я использую для хранения перечисления битмаски.Битмассная группировка с использованием SQLite

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

Услуги: имя TEXT, INTEGER службы, INTEGER маска

SELECT service,XXX FROM Services GROUP BY service 

В принципе, я бы например, XXX - результат битмаскировки OR (|) всех масок на эту службу.

данные:

'a1',1,1 
'a2',1,2, 
'a3',1,4, 
'a4',1,8, 

'b1',2,1, 
'b2',2,3, 
'b3',2,2 

Так как результат, я хотел бы получить следующие строки:

1,15 (1|2|4|8) 
2,3 (1|3|2) 

Благодарность

EDIT: В моем оригинальном вопросе, я «Я забыл упомянуть, что каждая маска не является одним битом, но может быть маской из нескольких бит (я изменил второй пример, чтобы отразить в).

+0

Я думаю, что в вашем примере вы имели в виду результаты, чтобы показать 2,3, так как это (1 | 2 | 2) на основе вашего примера – tawman

+0

вы правы - спасибо. Я исправил это. –

+0

Знаете ли вы все возможные значения маски растрового изображения раньше времени, которое вы будете использовать? то есть 1, 2, 4, ... 4096? – tawman

ответ

6

SQLite поддерживает настраиваемые агрегированные функции; в зависимости от вашей настройки вы могли бы register a custom function сделать это довольно легко. Использование API C:

void bitwise_or_step(sqlite3_context *context, int argc, sqlite3_value** argv) 
{ 
    int *buffer = (int *)sqlite3_aggregate_context(context, sizeof(int)); 
    int x = sqlite3_value_int(argv[0]); 
    *buffer |= x; 
} 

void bitwise_or_final(sqlite3_context *context) 
{ 
    int *buffer = (int *)sqlite3_aggregate_context(context, sizeof(int)); 
    sqlite3_result_int(context, *buffer); 
} 

sqlite3_create_function_v2(db, "BITWISE_OR", 1, SQLITE_ANY, NULL, 
    NULL, bitwise_or_step, bitwise_or_final, NULL); 

Тогда в вашем SQL, вы должны быть в состоянии сделать:

SELECT service,BITWISE_OR(mask) FROM Services GROUP BY service 

Если вы используете PHP, вы можете define a custom aggregate function from PHP тоже.

+0

спасибо, это работает как ожидалось. –

2

Битовой маска ИЛИ (|) операция целых чисел в SQL является простым делом подведения уникальной силы 2 значений для каждого ключа:

todd$ sqlite3 ex1 
SQLite version 3.7.5 
Enter ".help" for instructions 
Enter SQL statements terminated with a ";" 
sqlite> create table Services(Name varchar(100), Service int, mask int); 
sqlite> insert into Services values("a1", 1, 1); 
sqlite> insert into Services values("a2", 1, 2); 
sqlite> insert into Services values("a3", 1, 4); 
sqlite> insert into Services values("a4", 1, 8); 
sqlite> insert into Services values("b1", 2, 1); 
sqlite> insert into Services values("b2", 2, 3); 
sqlite> insert into Services values("b3", 2, 2); 
sqlite> select * from Services; 
a1|1|1 
a2|1|2 
a3|1|4 
a4|1|8 
b1|2|1 
b2|2|3 
b3|2|2 

EDIT: Когда вы знаете, домен растрового, вы можете bitand значение в его часть и сумма:

sqlite> select Service, max(mask&1) + max(mask&2) + max(mask&4) + max(mask&8) from Services group by Service; 
1|15 
2|3 
sqlite> 

вы можете продлить макс (маска & битной) логики для всех знают полномочие 2 вы хранящие в маске растровой.

+0

спасибо, но когда моя маска равна 7, это решение не будет работать –

+0

@ Gilad 7 не является силой 2, поэтому я не следую вашей логике. Предположение, основанное на вашем наборе данных, состоит в том, что каждая строка будет содержать одно значение битмапа для каждой строки. Вы по-прежнему можете использовать только SQL-подход, когда строка имеет комбинированное растровое изображение, но она более сложна с проверкой бит и проверкой и др. Нужен более качественный набор данных для иллюстрации. – tawman

+0

@ Гилад обновил мой ответ для комбинированного растрового сценария – tawman

Смежные вопросы