2012-02-02 5 views
6

Devo eseguire una query di selezione in una tabella di registrazione in cui è impostato un bit specifico di un numero intero. Il numero intero rappresenta un insieme di categorie in una maschera di bit: E.g.righe mySQL SELECT in cui è impostato un bit specifico di un intero

1 => health 
2 => marketing 
3 => personal 
4 => music 
5 => video 
6 => design 
7 => fashion 
8 => ...... 

esempio dati:

id | categories | title 
1 | 11   | bla bla 
2 | 48   | blabla, too 

ho bisogno di una query mysql che seleziona le registrazioni, che sono contrassegnati con una specifica categoria. Diciamo che "tutte le registrazioni video" Ciò significa ho bisogno di un set di risultati dei messaggi in cui è impostato il 5 ° bit della colonna catgories (ad esempio 16,17,48 ....)

SELECT * FROM postings WHERE ....???? 

Tutte le idee?

+1

Perché non solo una tabella aggiuntiva tra: categories_postings? Sarebbe una soluzione più a prova di futuro in quanto sembra solo un database standard di più categorie? –

+1

Sono d'accordo con Luc, sarà più semplice mantenere una tabella aggiuntiva chiamata, diciamo, categorie_groups, che avrà una struttura come: id, category_group_name, health, marketing, personal, music ... e che manterrà sia "0"/"1" sotto ogni categoria per contrassegnare se questa categoria appartiene a questo gruppo. In questo modo sarà anche molto più facile sommare il numero di gruppi che includono la categoria "salute". – alfasin

+0

@Luc - entrambi avete ragione - il fatto è che i dati sono pubblicati da un'applicazione esterna in cui non posso apportare modifiche. Una relazione molti-molti sarebbe la soluzione migliore ... – derRobert

risposta

9

È possibile utilizzare gli operatori bitwise come questo. Per il video (bit 5):

WHERE categories & 16 = 16 

sostituire il valore 16 utilizzando i seguenti valori per ogni bit:

1 = 1 
2 = 2 
3 = 4 
4 = 8 
5 = 16 
6 = 32 
7 = 64 
8 = 128 

Questo va dal bit meno significativo al più alto, che è opposto della strada maggior parte dei programmatori pensare. Anche loro partono da zero.

+0

Le mappature precedenti possono essere semplificate come: bitVal = 2^(i-1), dove i è il valore dell'indice sulla sinistra. Quindi, ad esempio, 16 = 2^(5-1). –

2

Come su

SELECT * FROM postings WHERE (categories & 16) > 0; -- 16 is 5th bit over 

Un problema con questo è probabilmente non vi ha colpito un indice, così si potrebbe incorrere in problemi Potenza se si tratta di una grande quantità di dati.

Alcuni database (come PostgreSQL) consentono di definire un indice su un'espressione come questa. Non sono sicuro che mySQL abbia questa funzionalità. Se questo è importante, potresti prendere in considerazione la possibilità di suddividerli in colonne booleane separate o in una nuova tabella.

-1

SQL (non solo mySQL) non è adatto per operazioni bit a bit. Se si esegue un bit AND, si imporrà una scansione della tabella poiché SQL non sarà in grado di utilizzare alcun indice e dovrà controllare ogni riga una alla volta.

Sarebbe meglio se si creasse una tabella "Categorie" separata e una tabella PostingCategoria molti-a-molti indicizzata per connettere i due.

UPDATE

Per le persone insistendo sul fatto che i campi bitmap non sono un problema, aiuta a controllare Joe Celko di BIT of a Problem. In fondo all'articolo c'è una lista di problemi seri causati da bitmap.

Per quanto riguarda il commento che una dichiarazione generale non può essere giusto, nota # 10 - si rompe 1NF quindi sì, campi bitmap sono cattivi:

  1. I dati sono illeggibili. ...
  2. I vincoli sono un b #### per scrivere ....
  3. Sei limitato a due valori per campo. Questo è molto restrittivo; anche il codice ISO ISO non può essere inserito in una colonna del genere ...
  4. Non c'è alcun elemento temporale nella maschera di bit (o nei flag di bit singoli). Ad esempio, un flag "is_legal_adult_flg" ... Una DATA per la data di nascita (solo 3 byte) manterrebbe il fatto completo e calcoliamo ciò che dobbiamo sapere; sarebbe sempre corretto anche ...
  5. Si scoprirà che l'utilizzo dei flag tenderà a dividere lo stato di un'entità su più tabelle ....
  6. I bit flag invitano la ridondanza. Nel sistema che ho appena menzionato, avevamo "is_active_flg" e "is_completed_flg" nella stessa tabella. Un'asta completata non è attiva e vice versa. È lo stesso fatto in due bandiere. La psicologia umana (e la lingua inglese) preferisce ascoltare una frase affermativa (ricorda la vecchia canzone "Sì, non abbiamo banane oggi!"?). Tutti questi flag di bit e la convalida della sequenza vengono sostituiti da due serie di tabelle di transizione di stato, una per le offerte e una per le spedizioni. Per dettagli sui vincoli di transizione dello stato. La storia di ogni asta è ora in un posto e deve seguire le regole di business.
  7. Nel momento in cui si disassembla una colonna di maschera di bit e si eliminano i campi non necessari, le prestazioni non saranno migliorate su tipi di dati più semplici.
  8. Raggruppare e ordinare i singoli campi è un vero dolore. Provalo.
  9. Devi indicizzare l'intera colonna, quindi a meno che tu non sia fortunato e li abbia nel giusto ordine, sei bloccato con le scansioni delle tabelle.
  10. Poiché un bit mask non è in First Normal Form (1NF), si hanno tutte le anomalie che si desidera evitare in RDBMS.

Vorrei anche aggiungere, per quanto riguarda i valori NULL? Che dire di senza bandiere? E se qualcosa non fosse né vero né falso?

Infine, per quanto riguarda la richiesta di compressione, la maggior parte dei database racchiude i campi di bit in byte e interi internamente. Il campo bitmap non offre alcun tipo di compressione in questo caso. Altri database (ad esempio PostgreSQL) hanno effettivamente un tipo booleano che può essere vero/falso/sconosciuto. Può richiedere 1 byte ma è non un sacco di spazio di archiviazione e la compressione trasparente è disponibile se una tabella diventa troppo grande.

Infatti, se una tabella diventa grande i campi bitmap diventano molto più gravi. Salvare pochi MB in una tabella GB non è un guadagno se si è costretti a utilizzare le scansioni di tabelle o se si perde la possibilità di raggruppare

+0

Questa è una dichiarazione troppo generica per essere accurata. È vero che non sarai in grado di eseguire scansioni di indice in campi bit a bit, tuttavia, possono spesso tornare utili e portare a una riduzione massiccia delle dimensioni dello spazio di archiviazione o alla velocità di query a seconda di ciò che stai cercando. – delrox

+1

Se la ricerca utilizza solo il campo bitmap per "l'ultimo miglio" - in altre parole hai ristretto una ricerca molto più ampia a poche centinaia di record o più usando altri campi/indici - allora non c'è molto di un problema con cui preoccuparsi. Per i set di dati statici forti i campi bitmap sono, come altri hanno già detto, una buona forma di compressione dei dati. (Non aggiungeremo un nuovo giorno alla settimana né nuove ore in un giorno in qualunque momento, ad esempio ...) – Techmag

+1

@Techmag in realtà, no. I DBA tipicamente odiano i campi bitmap perché causano un * LOTTO * di problemi, la performance uno di essi. Rendono illeggibili i dati, impediscono l'uso di vincoli e altro ancora. Controlla [BIT of a Problem] di Joe Celko (https://www.simple-talk.com/sql/t-sql-programming/bit-of-a-problem/). Quello che chiamate compressione, specialmente per giorni, verrebbe sostituito con un valore di tipo o enum semplice. In effetti, si potrebbe discutere di compressione * solo * se si potesse usare tutti i bit sul campo di supporto. Altrimenti verrebbe sprecato, ad esempio 7 bit su un bield a 16 bit –