StringInString Query? - PullRequest
       1

StringInString Query?

0 голосов
/ 04 мая 2011

У меня есть база данных, в которой я хранил некоторые теги.Я сохранил теги так:

"humor,funny,animal"

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

SELECT id FROM database WHERE tags REGEXP 'humor' LIMIT 1

К сожалению, это не работает.Может ли кто-нибудь из вас помочь мне?

Редактировать: Спасибо за все ответы!Теперь мне нужно сначала изучить это!Но проблема решена:)

Ответы [ 3 ]

1 голос
/ 04 мая 2011

Краткосрочный

Поскольку теги хранятся в виде денормализованных данных, используйте функцию FIND_IN_SET :

SELECT t.id
  FROM YOUR_TABLE t
 WHERE FIND_IN_SET('humour', t.tags) > 0

Долгосрочное решение

Настройкатаблицы для правильной обработки отношения «многие ко многим»:

TAGS

  • tag_id (первичный ключ)
  • tag_description

ITEMS

  • item_id (первичный ключ)

ITEM_TAGS

  • item_id (первичный ключ, внешний ключ для ITEMS.item_id)
  • tag_id (первичный ключ, внешний ключ для TAGS.tag_id)

Если сделать два столбца в ITEM_TAGS первичным ключом, вам не придется беспокоиться о дубликатах.И да, это означает использование движка InnoDB ...

Затем вы можете использовать:

SELECT i.item_id
  FROM ITEMS i
 WHERE EXISTS (SELECT NULL
                 FROM ITEM_TAGS it
                 JOIN TAGS t ON t.tag_id = it.tag_id
                WHERE t.tag_description = 'humour'
                  AND it.item_id = i.item_id)
0 голосов
/ 04 мая 2011

Вы можете использовать LIKE

 SELECT id FROM database WHERE tags LIKE '%humor%' LIMIT 1

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

Но, как говорили другие, лучше всего иметь отдельную таблицу для тегов. Для этого вам также понадобится сводная таблица.

Например,

--------------  data  -------------
|     ID         |     NAME       | 
| 1              | example        |
| 2              | example 2      | 
-----------------------------------

--------------  tags  -------------
|      ID        |     NAME       |
| 1              | humor          |
| 2              | cats           |
| 3              | wumpus         |
-----------------------------------

------------  data_tags  ----------
|   DATA_ID      |   TAG_ID       |
| 1              | 1              |
| 1              | 2              |
| 2              | 1              |
| 2              | 3              |
-----------------------------------
0 голосов
/ 04 мая 2011

Чтобы расширить комментарий Томалака, лучше всего решить эту проблему, используя отношение «многие ко многим» для отношений от database до tag. Это включает в себя добавление двух новых таблиц. Как то так (простите мой ржавый MySQL)

CREATE TABLE `Tag` (
    id  INT(11)     UNSIGNED NOT NULL AUTO_INCREMENT,
    tag VARCHAR(64) NOT NULL,
    PRIMARY KEY (id),
    UNIQUE      (tag)
) ENGINE=InnoDB;

CREATE TABLE `DatabaseTag` (
    database_id INT(11) UNSIGNED NOT NULL, -- just guessing your database.id type here
    tag_id      INT(11) UNSIGNED NOT NULL,
    PRIMARY KEY (database_id, tag_id),
    FOREIGN KEY (database_id) REFERENCES `database` (id)
        ON DELETE CASCADE,
    FOREIGN KEY (tag_id)      REFERENCES `Tag` (id)
        ON DELETE CASCADE
) ENGINE=InndoDB;

Затем, чтобы найти все database записи, соответствующие тегу "юмор", ваш запрос будет выглядеть как

SELECT id FROM `database` d
INNER JOIN `DatabaseTag` dt ON d.id = dt.database_id
INNER JOIN `Tag` t ON dt.tag_id = t.id
WHERE t.tag = 'humour'
...