1 votes

Comment interroger un tableau de caractères 1 et 0 à partir d'une base de données ?

Supposons que vous ayez un long tableau de caractères qui sont soit 1 soit 0, un peu comme un vecteur de bits, mais sur une colonne de base de données. Comment pourriez-vous faire une requête pour savoir quelles valeurs sont définies ou non définies ? Supposons que vous ayez besoin de savoir si les caractères 500 et 1500 sont "vrais" ou non.

6voto

Tomalak Points 150423
SELECT
  Id
FROM
  BitVectorTable
WHERE
  SUBSTRING(BitVector, 500, 1) = '1'
  AND SUBSTRING(BitVector, 1000, 1) = '1'

Aucun index ne peut être utilisé pour ce type de requête. Lorsque vous avez beaucoup de lignes, cela devient très vite lent.

Edit : Sur SQL Server au moins, toutes les fonctions de chaînes de caractères intégrées sont déterministe . Cela signifie que vous pourriez envisager la possibilité de créer des colonnes calculées basées sur les résultats de SUBSTRING() pour l'ensemble de la valeur combinée, mettre un index sur chacun d'entre eux . Les insertions seront plus lentes, la taille des tables augmentera, mais les recherches seront très rapides.

SELECT
  Id
FROM
  BitVectorTable
WHERE
  BitVector_0500 = '1'
  AND BitVector_1000 = '1'

Edit #2 : Le limites pour SQL Server sont :

  • 1 024 colonnes par table normale
  • 30 000 colonnes par table "large

3voto

Paul Dixon Points 122033

Dans MySQL, l'utilisation de sous-chaîne comme

select foo from bar 
where substring(col, 500,1)='1' and substring(col, 1500,1)='1';

Cela sera cependant assez inefficace, vous devriez peut-être repenser votre schéma. Par exemple, vous pourriez stocker chaque bit séparément afin d'échanger de l'espace contre de la vitesse...

create table foo
(
   id int not null,
   bar varchar(128),
   primary key(id)
);

create table foobit
(
   int foo_id int not null,
   int idx int not null,
   value tinyint not null,

   primary key(foo_id,idx),
   index(idx,value)
);

Qui serait interrogé

   select foo.bar from foo
   inner join foobit as bit500
      on(foo.id=bit500.foo_id and bit500.idx=500)
   inner join foobit as bit1500
      on(foo.id=bit1500.foo_id and bit1500.idx=1500)
   where
      bit500.value=1 and bit1500.value=1;

Elle consomme évidemment plus d'espace de stockage, mais devrait être plus rapide pour ces opérations d'interrogation puisqu'un index sera utilisé.

2voto

soulmerge Points 37314

Je convertirais la colonne en plusieurs colonnes de bits et réécrirais le code correspondant - les masques de bits sont tellement plus rapides que les comparaisons de chaînes. Mais si vous ne pouvez pas faire cela, vous devez utiliser des fonctions spécifiques à la base de données. Les expressions régulières pourraient être une option

-- Flavor: MySql
SELECT * FROM table WHERE column REGEXP "^.{499}1.{999}1"

1voto

tehvan Points 3949
select substring(your_col, 500,1) as char500,
substring(your_col, 1500,1) as char1500 from your_table;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X