SubQuery中的MySql IN子句问题

时间:2015-08-18 11:44:28

标签: mysql

SELECT users.id, (SELECT GROUP_CONCAT(languages.language) FROM languages WHERE languages.id IN (users.languages)) as languages FROM users

在我的users.languages列中,值为3,2,5

当我直接放置该值时,它会返回英语,德语,法语。但是当我在IN子句中放置users.languages时,它只返回英语。有谁知道我错过了什么。

Languages table
id  language    lang_code
1   English     en
2   Dutch       nl
3   German      de
4   Spanish     fr
5   French      es

Users table
id languages
1  1,3,5

2 个答案:

答案 0 :(得分:2)

应该是另一个SELECT查询返回一列:

SELECT `users`.`id`, (
  SELECT GROUP_CONCAT(`languages`.`language`) FROM `languages`
  WHERE `languages`.`id` IN (
    SELECT `languages` FROM `users`
  )
) as `languages` FROM `users`

答案 1 :(得分:1)

您不应将列表存储在以逗号分隔的字符串中。以下是几个很好的理由:

  • 数字应存储为数字,而不是字符串。
  • Ids应该已经识别出外键关系,将整数存储为字符串时无法做到。
  • SQL(一般情况下)对字符串的支持不足。

存储此类列表的正确方法是联结表。在您的情况下,这将是UserLanguages,每次使用一行,每种语言一行。

那就是说,有时候我们会遇到其他人非常非常糟糕的设计决策。 MySQL提供find_in_set()来帮助解决这种情况:

SELECT u.id,
      (SELECT GROUP_CONCAT(l.language)
       FROM languages l
       WHERE FIND_IN_SET(l.id, u.languages)
      ) as languages
FROM users u;

但是,使用联结表的正确查询是:

SELECT u.id,
      (SELECT GROUP_CONCAT(l.language)
       FROM UserLanguages ul JOIN
            languages l
            ON ul.LanguageId = l.id
       WHERE ul.UserId = u.id
      ) as languages
FROM users u;