Запрос данных из строки или сериализованного массива - PullRequest
1 голос
/ 13 сентября 2011

Мне нужно сделать запрос из столбца, который содержит строки, которые выглядят так: Язык1, Язык2, Язык3 .

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

Так что мне интересно, какой самый эффективный / элегантный способ запроса данных внутри этой строки?

Должен ли я использовать сериализованные данные? Что бы запрос, который извлекает все соответствующие строки, скажет "Language2"?

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

Второе редактирование Вот вид моей таблицы, какой она есть сейчас: my table as it is right now

Ответы [ 4 ]

3 голосов
/ 12 марта 2014

Я искал решение для того же сценария для запроса данных в сериализованном массиве и обнаружил, что использование функции SUBSTRING_INDEX() делает свою работу.Пример ниже:

| language             |
------------------------
| a:1:{i:1;s:3:"183";} |

, чтобы получить цифру '183' (без кавычек), запрос будет выглядеть примерно так:результат нижеприведенного без кавычек:

| language_id          |
------------------------
| 183                  |
2 голосов
/ 13 сентября 2011

Хотя Shef и ajreal верны, поскольку с точки зрения дизайна было бы лучше нормализовать таблицы, чтобы ответить на ваш реальный вопрос, вы можете просто использовать LIKE:

SELECT * FROM personnel WHERE languages LIKE '%English%';

Однако вы можете столкнуться с проблемами, если языки свободны от текста, так как кто-то, возможно, ввел «английскую» или другую заглавную букву, поэтому вам нужно:

SELECT * FROM personnel WHERE UPPER(languages) LIKE '%ENGLISH%';

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

;value3;value4;value12;

Это позволяет вам искать

LIKE '%;value1;%'

без совпадения value11 или value12.

Иногда вам действительно нужно поведение сопоставления подстроки, например, если кто-то ответил British English, вам может потребоваться совпадение English. (хотя, если они вводят British, вы SOL) ... но если вы сталкиваетесь с этими проблемами, вы, вероятно, захотите определить иерархию или использовать кодировку, поскольку вы не можете зависеть от работы подстрок.

2 голосов
/ 13 сентября 2011

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

Создать отдельную таблицу, в которой будут храниться ссылки на отношения.

table_languages ​​

ref_id | language

Пример данных:

user_id | language
-------------------
   1   | Language 1
   1   | Language 2
   1   | Language 3
   2   | Language 2

Пример запроса:

    SELECT *
      FROM users u
INNER JOIN languages l
        ON u.user_id = l.user_id
       AND l.language = 'language2'
     WHERE u.country = 'abc'
       AND u.city = 'def';
1 голос
/ 13 сентября 2011

Не делай этого.
Один пример для нормализации

create table language
(
  id smallint(10) unsigned not null default 0,
  name varchar(255) not null,
  primary key(id),
  key (name)
);

-- assuming your table is named as data
create table data
(
  id int(10) not null default 0,
  -- plus any of your existing column definition
  key(id)
);

-- build a relation table to tied knot between language and data
create table data_language
(
  data_id int(10) not null not null default 0,
  language_id smallint(10) unsigned not null default 0,
  key (data_id, language_id)
);

-- when select
select data.id, language.id, language.name
from data
inner join (data_language, language)
on data.id=data_language.data_id and language.id=data_language.language_id
where language.name='English'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...