use*_*861 1 mysql database-design
我网站上的用户必须能够选择他们知道的语言(英语、德语等),所以我有一个languages
包含 150 种语言(id、名称)和表users
(id 和许多其他字段)的表。
网站的访问者必须能够通过他们的语言知识来搜索用户。例如,他们可能正在寻找擅长英语、德语和法语的人。
我无法解决这个问题。如果我创建一个language_knowledge
包含字段 id、language_id 和 user_id 的表,那么我将能够找到知道一种特定语言(比如英语)的用户,但我需要找到知道的用户,例如,英语和德语。
我该怎么做呢?
这是您使用连接表的经典情况(可以在此处找到基于此的小提琴。它比原始答案晚得多 - 语言表的 PRIMARY KEY 的更好候选者!。
CREATE TABLE user
(
user_id INT,
user_name VARCHAR(25),
PRIMARY KEY (user_id)
);
CREATE TABLE language
(
iso_code CHAR(2), -- or whatever you want the PRIMARY KEY to be.
language_name VARCHAR(30),
PRIMARY KEY (iso_code)
);
CREATE TABLE user_language
(
ul_user_id INT,
ul_iso_code CHAR(2),
PRIMARY KEY (ul_user_id, ul_iso_code),
FOREIGN KEY (ul_user_id) REFERENCES user (user_id),
FOREIGN KEY (ul_iso_code) REFERENCES language (iso_code)
);
Run Code Online (Sandbox Code Playgroud)
我忘了提到 FOREIGN KEY必须指向引用表中的 PRIMARY KEY 或 UNIQUE KEY(而不是其他任意字段)。
为了完整起见,您应该在两个连接字段上放置一个 PRIMARY KEY。这将有助于查询响应时间并避免多次输入相同数据。无论您的应用程序做什么,始终尝试在数据库中强制执行 RI(参照完整性)。
该查询展示了如何获得用户ID和名称的人谁知道这两个英语和德语。
SELECT ul_user_id
, user_name
FROM user_language ul
INNER JOIN language l ON ul.ul_iso_code = l.iso_code
INNER JOIN user u ON u.user_id = ul.ul_user_id
WHERE l.language_name IN (
'English'
, 'German'
)
GROUP BY ul_user_id, user_name
HAVING COUNT(*) = 2;
Run Code Online (Sandbox Code Playgroud)
该HAVING COUNT(*) = 2
条款将结果仅限于同时了解两种语言的人。如果该IN (...)
条款有 3 种不同的语言,则您需要修改该HAVING
条款以反映这一点,例如: HAVING COUNT(*) = 3