Как бы вы запросили массив символов 1 и 0 из базы данных? - PullRequest
1 голос
/ 13 февраля 2009

Скажем, у вас был длинный массив символов, равный 1 или 0, что-то вроде bitvector, но в столбце базы данных. Как бы вы запросили, чтобы узнать, какие значения установлены / не установлены? Скажем, вам нужно знать, являются ли char 500 и char 1500 "истинными" или нет.

Ответы [ 4 ]

6 голосов
/ 13 февраля 2009
SELECT
  Id
FROM
  BitVectorTable
WHERE
  SUBSTRING(BitVector, 500, 1) = '1'
  AND SUBSTRING(BitVector, 1000, 1) = '1'

Однако для этого типа запроса индекс не может быть использован. Когда у вас много строк, это очень медленно замедляется.

Редактировать: По крайней мере, в SQL Server все встроенные строковые функции являются детерминированными . Это означает, что вы могли бы рассмотреть возможность создания вычисляемых столбцов на основе результатов SUBSTRING () для всего объединенного значения, с указанием индекса каждого из них . Вставки будут медленнее, размер таблицы увеличится, но поиск будет очень быстрым.

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

Редактировать # 2: ограничения для SQL Server :

  • 1024 столбца на обычную таблицу
  • 30 000 столбцов на «широкую» таблицу
3 голосов
/ 13 февраля 2009

В MySQL что-то, использующее подстроку , как

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

Это будет довольно неэффективно, хотя, возможно, вы захотите пересмотреть свою схему. Например, вы можете хранить каждый бит отдельно, чтобы обменять пространство на скорость ...

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)
);

Что будет запрошено

   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;

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

2 голосов
/ 13 февраля 2009

Я бы преобразовал столбец в несколько битовых столбцов и переписал соответствующий код - битовые маски намного быстрее, чем сравнения строк. Но если вы не можете этого сделать, вы должны использовать специфичные для БД функции. Регулярные выражения могут быть опцией

-- Flavor: MySql
SELECT * FROM table WHERE column REGEXP "^.{499}1.{999}1"
1 голос
/ 13 февраля 2009
select substring(your_col, 500,1) as char500,
substring(your_col, 1500,1) as char1500 from your_table;
...