mysql查询中的复杂搜索问题

时间:2011-06-10 12:48:18

标签: mysql ruby-on-rails-3

我的数据库中有模型(表格),表格和字段名称如

tags                 (id, name)
taggings             (id, tag_id, taggable_id, taggable_type, context)
employment_histories (id, user_id, grades, subjects, my_interests )
users                (id)

taggable_id实际上是employment_histories_id,上下文可以是成绩或科目或my_interests

现在我有一系列标签,例如G = { “第九”, “10日”} 我希望获得用户,只有其标签与上述g数组匹配。

我写了下面的查询:

SELECT DISTINCT users.* FROM `users` 
LEFT OUTER JOIN `employment_histories` 
  ON `employment_histories`.`user_id` = `users`.`id` 
LEFT OUTER JOIN `taggings` 
  ON `employment_histories`.`id` = `taggings`.`taggable_id` 
  AND `taggings`.`taggable_type` = 'EmploymentHistory' 
LEFT OUTER JOIN `tags` ON taggings.context = 'subjects' 
WHERE tags.name='9th' OR tags.name='10th'

但是它也给了我那些与任何标签匹配的用户,但我希望它只返回匹配所有两个标签的用户

假设标签9和10具有标签id 9和10然后我想要它只返回taggable_id(对于jobshistories.id),这对于这两个tag_id(即9和10)在标签中有共同的taggable_id表

例如我有两个用户tariq和kamal,这两个用户都有第9个标签常见但kamal没有标记10th所以想要查询如果通过这两个标签应该只返回tariq,其标签都是这两个标签但是用户喜欢与任何标签匹配的kamal也应该过滤

3 个答案:

答案 0 :(得分:2)

SELECT users.* FROM users 
INNER JOIN employment_histories 
  ON employment_histories.user_id = users.id 
INNER JOIN taggings 
  ON employment_histories.id = taggings.taggable_id 
  AND taggings.taggable_type = 'EmploymentHistory' 
  AND taggings.context = 'subjects'
INNER JOIN tags ON tags.id = taggings.tag_id
WHERE tags.name IN ('9th','10th')
GROUP BY users.id
HAVING COUNT(DISTINCT(tags.name)) = 2;

答案 1 :(得分:2)

来自php chat room

SELECT
users.* ,
count(*) AS count
FROM users
    LEFT JOIN employment_histories ON  users.id = employment_histories.user_id
    LEFT JOIN tagging ON tagging.taggable_id = employment_histories.id
    LEFT JOIN tags ON tags.id = tagging.tag_id
WHERE tags.name = "9th"
       OR tags.name = "10th"
GROUP BY users.id
HAVING count = 2

答案 2 :(得分:1)

我重新编写了查询。

几乎没有变化:

  • 加入tags.id = taggings.tag_id
  • 上的标签
  • 从where子句中删除OR,并使用in,提高性能。
   SELECT DISTINCT users.*, count(*) as totRow FROM `users` 
   LEFT OUTER JOIN `employment_histories`
   ON `employment_histories`.`user_id` =
   `users`.`id`  LEFT OUTER JOIN
   `taggings`    ON
   `employment_histories`.`id` =
   `taggings`.`taggable_id`    AND
   `taggings`.`taggable_type` =
  'EmploymentHistory'    AND
   `taggings`.`context` = 'subjects' 
   LEFT OUTER JOIN `tags` ON `tags`.`id` = `taggings`.`tag_id` 
  WHERE tags.name = '9th' or tags.name = '10th'
  GROUP BY `users`.`id`