我会像这样设置三张桌子
CREATE TABLE languages
(
`id` int not null auto_increment primary key,
`language` varchar(32) unique
);
CREATE TABLE users
(
`id` int not null auto_increment primary key,
`name` varchar(32)
);
CREATE TABLE user_language
(
`user_id` int,
`language_id` int,
primary key (user_id, language_id)
);
恕我直言,如果您没有数以百万计的用户和所有可能的语言并寻求灵活性而不是为毫秒而战,特别是如果您一次检查超过 2 种语言,您可以使用 MAX() 或SUM() 聚合在 HAVING 子句中。
这里有一些示例查询:
-- Speaks both French AND Spanish
SELECT u.name
FROM user_language ul JOIN languages l
ON ul.language_id = l.id JOIN users u
ON ul.user_id = u.id
GROUP BY u.id
HAVING MAX(l.language = 'french') = 1
AND MAX(l.language = 'spanish') = 1;
输出:
|姓名 |
|--------|
|约翰 |
|杰克 |
-- Speaks both French OR Spanish
SELECT u.name
FROM user_language ul JOIN languages l
ON ul.language_id = l.id JOIN users u
ON ul.user_id = u.id
GROUP BY u.id
HAVING MAX(l.language = 'french') +
MAX(l.language = 'spanish') > 0;
输出:
|姓名 |
|--------|
|约翰 |
|杰克 |
|吉尔 |
-- Speaks any language French OR Spanish BUT NOT English
SELECT u.name
FROM user_language ul JOIN languages l
ON ul.language_id = l.id JOIN users u
ON ul.user_id = u.id
GROUP BY u.id
HAVING MAX(l.language = 'french') +
MAX(l.language = 'spanish') > 0
AND MAX(l.language = 'english') = 0;
输出:
|姓名 |
|--------|
|杰克 |
-- Speaks any language but English
SELECT u.name
FROM user_language ul JOIN languages l
ON ul.language_id = l.id JOIN users u
ON ul.user_id = u.id
GROUP BY u.id
HAVING MAX(l.language = 'english') = 0;
输出:
|姓名 |
|--------|
|杰克 |
-- What languages does Jack speak
SELECT l.language
FROM user_language ul JOIN languages l
ON ul.language_id = l.id JOIN users u
ON ul.user_id = u.id
WHERE u.name = 'Jack';
输出:
|语言 |
|-----------|
|法语 |
|西班牙语 |
-- How many languages do users speak
SELECT u.name, COUNT(*) no_of_languages
FROM users u LEFT JOIN user_language ul
ON u.id = ul.user_id
GROUP BY u.id;
输出:
|姓名 | NO_OF_LANGUAGES |
|--------|-----------------|
|约翰 | 3 |
|杰克 | 2 |
|吉尔 | 2 |
-- How many users do speak a particular language
SELECT l.language, COUNT(*) no_of_users
FROM languages l LEFT JOIN user_language ul
ON l.id = ul.language_id
GROUP BY l.id;
输出:
|语言 | NO_OF_USERS |
|------------|-------------|
|英语 | 2 |
|法语 | 2 |
|西班牙语 | 3 |
现在在真正的应用程序中,您很可能不会使用语言或用户名,而是处理来自您的 UI(下拉框或任何)。因此,您将能够从等式中消除一个联接,并且您的查询看起来会像这样
-- Speaks both French AND Spanish with Ids
SELECT u.name
FROM user_language ul JOIN users u
ON ul.user_id = u.id
GROUP BY u.id
HAVING MAX(ul.language_id = 2) = 1
AND MAX(ul.language_id = 3) = 1;
这里是SQLFiddle演示