开发者

StringInString Query?

I have this database where I have stored some tags in it. I stored the tags like this:

"humor,funny,animal"

Now I need a mysql query that selects this line when I search for "humor", "funny" or "animal". What I have until开发者_如何转开发 now:

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

Unfortunately, it does not work. Could someone of you please help me out?

Edit: Thanks for all the responses! I will now need to study this first! But problem solved :)


Short Term

Because the tags are stored as denormalized data, use the FIND_IN_SET function:

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

Long Term Solution

Setup the tables to properly handle a many-to-many relationship:

TAGS

  • tag_id (primary key)
  • tag_description

ITEMS

  • item_id (primary key)

ITEM_TAGS

  • item_id (primary key, foreign key to ITEMS.item_id)
  • tag_id (primary key, foreign key to TAGS.tag_id)

Making the two columns in ITEM_TAGS the primary key means you don't have to worry about duplicates. And yes, this means using the InnoDB engine...

Then, you can use:

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)


You can use LIKE

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

Which will search for any entry where 'humor' is a substring. Note this will also return items tagged 'humorous'.

But like others said, having a separate table for tags would be best. To do this you will also need a pivot table.

So for example

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


To expand on Tomalak's comment, this would be best solved using a many-to-many relationship for database to tag relationships. This involves adding two new tables. Something like this (forgive my rusty 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;

Then, to find all the database records matching tag "humour", your query would look like

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'
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜