【问题标题】:Complex search problem in mysql querymysql查询中的复杂搜索问题
【发布时间】:2011-06-10 12:48:18
【问题描述】:

我的数据库中有模型(表),表和字段名称类似于

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,上下文可以是成绩或科目或我的兴趣

现在我有了标签数组,例如g={"9th","10th"} 我想获取用户,只有其标签都与上面的 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(即就业历史.id),这两个 tag_id(即 9 和 10)在标签中具有共同的 taggable_id表

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

【问题讨论】:

    标签: mysql ruby-on-rails-3


    【解决方案1】:

    来自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】:
      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;
      

      【讨论】:

      【解决方案3】:

      我已经重写了查询。

      变化不大:

      • 在 tags.id = taggings.tag_id 上加入标签
      • 从 where 子句中删除 OR 并使用 in 可以提高性能。
      SELECT DISTINCT users.*, count(*) as totRow FROM `users` 左外连接`employment_histories` ON `employment_histories`.`user_id` = `users`.`id` 左外连接 `标签`开启 `employment_histories`.`id` = `taggings`.`taggable_id` AND `taggings`.`taggable_type` = “就业历史”和 `taggings`.`context` = 'subjects' 左外连接 `tags` ON `tags`.`id` = `taggings`.`tag_id` WHERE tags.name = '9th' 或 tags.name = '10th' GROUP BY `users`.`id`

      【讨论】:

      • 对不起伙计,它也没有给我想要的东西。假设我有两个用户 tariq 和 kamal 并且都有第 9 个标签 common 但 kamal 没有标签名称 1oth 所以它应该排除 kamal 并且只显示 tariq
      • 这意味着您需要那些必须有标签“9th”和“10th”的用户,如果这是正确的,请查看查询的更新版本。
      • 不,亲爱的,它不会工作,并且在两个标签之间放置 and 意味着标签名称应该同时满足第 9 和第 10 的时间,我们不能放置和高于应该放置的标签比如搜索第 9 个标签名和第 10 个标签名搜索,然后我们将检查这两个搜索是否有工作 ID 是否相同,这在 taggsings 表中称为 taggable_id
      猜你喜欢
      • 2019-12-19
      • 1970-01-01
      • 1970-01-01
      • 2013-07-19
      • 1970-01-01
      • 1970-01-01
      • 2012-12-24
      • 2018-04-19
      • 1970-01-01
      相关资源
      最近更新 更多