开发者

Get MysQL rows where 2 words match

I am trying to build an easy search based on 2 MySQL tables. One called keywords (words) and another called keyword2data (map which binds words to datasource).

Keywords holds id and keyword whilst keywords2data holds keyword_id and data_id.

data_id it self is a reference to a 3rd but in this case unimportant table.

What i want is to be able to search for example "dog sled" and get all data_id's which has those keywords bound to it.

SELECT k2d.`data_id` , k2d.`keyword_id` 
FROM keywords2data as k2d, keywords as k 
WHERE k2d.`keyword_id` = k.`id` 
&& (k.`keyword` = 'dog' || k.`keyword` = 'sled') 
LIMIT 10

Gives me all data_id which has either dog or sled bound to it, not necessary both, which is what i want.

SELECT k2d.`data_id` , k2d.`keyword_id` 
FROM keywords2data as k2d, keywords as k 
WHERE k2d.`keyword_id` = k.`id` 
&开发者_如何学运维& (k.`keyword` = 'dog' && k.`keyword` = 'sled') 
LIMIT 10

Gives me nothing since no single row in keywords2data holds 2 keywords.

What is the right way to do this?


How about something like

SELECT  k2d.`data_id` , 
        k2d.`keyword_id`  
FROM    keywords2data as k2d INNER JOIN
        keywords as k  ON k2d.`keyword_id` = k.`id` INNER JOIN
        keywords as k2  ON k2d.`keyword_id` = k2.`id`
WHERE   k.`keyword` = 'dog' 
AND     k2.`keyword` = 'sled'
LIMIT 10 


How about this?

SELECT k2d.`data_id`, 
       k2d.`keyword_id` 
FROM   keywords2data AS k2d 
       INNER JOIN keywords AS k 
         ON k2d.`keyword_id` = k.`id` 
WHERE  k.`keyword` IN ( 'dog', 'sled', 'rex' ) 
GROUP  BY k.keyword 
HAVING COUNT(*) = 3 


Possibly, this?

To extend to match more keywords you'd just add more words to the OR statement in the subquery and change the =2 afterwards.

This assumes that each data item is linked to a keyword using kerywords2data once and only once.

SELECT k2d.data_id
     , k2d.keyword_id

FROM keywords2data AS k2d
   , keywords AS k 

WHERE k2d.keyword_id = k.id
  AND (
       SELECT COUNT(*)
        FROM keywords2data AS sqk2d
           , keywords AS sqk 
        WHERE sqk2d.data_id = k2d.data_id
          AND sqk2d.keyword_id = sqk.id
          AND (sqk.keyword = 'dog' || sqk.keyword = 'sled')
       ) = 2

LIMIT 10

Here's a version that doesn't return the data_id repeated (as per comments), but also doesn't return any keywords at all:

SELECT k2d.data_id

FROM keywords2data AS k2d

WHERE (
       SELECT COUNT(*)
         FROM keywords2data AS sqk2d
            , keywords AS sqk 
        WHERE sqk2d.data_id = k2d.data_id
          AND sqk2d.keyword_id = sqk.id
          AND (sqk.keyword = 'dog' || sqk.keyword = 'sled')
      ) = 2

LIMIT 10
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜