构建基于标签的内部电话簿并创建了一个链接表,但无法看到如何加入选择所有来自阿伯丁和曼彻斯特的经理和导演的人。
用户
ID | Name | etc
1 | Frank
2 | Bob
3 | Bert
标签
ID | TagName | Tag Order
1 | Aberdeen | 1
2 | Manchester | 1
3 | Staff | 2
4 | Manager | 2
5 | Director | 2
链接表
ID | UsersId | TagsId
1 | 1 | 1
2 | 2 | 1
3 | 3 | 2
如果选择了标签Aberdeen,它将显示Frank和Bob 如果选择了标签曼彻斯特,它将显示Bert 我想选择Tag Aberdeen和Tag Manchester来向大家展示 然后我想选择所有来自阿伯丁和曼彻斯特的经理和董事。
尝试编写SQL是一项艰难的任务,任何想法,都要提前感谢。
答案 0 :(得分:0)
你需要两个连接。例如,这将显示所有来自阿伯丁或曼彻斯特的人:
select
u.ID,
u.Name
from
Users as u
inner join LinkingTable as l on t.UsersID=u.ID
inner join Tags as t on t.ID=l.TagsID
where
t.TagName in ('Aberdeen', 'Manchester')
这将选择所有经理和董事:
select
u.ID,
u.Name
from
Users as u
inner join LinkingTable as l on t.UsersID=u.ID
inner join Tags as t on t.ID=l.TagsID
where
t.TagName in ('Manager', 'Director')
如果要从Aberdeen或Manchester选择经理和总监,则需要选择这两个表中出现的行。这可以使用intersect
select
u.ID,
u.Name
from
Users as u
inner join LinkingTable as l on t.UsersID=u.ID
inner join Tags as t on t.ID=l.TagsID
where
t.TagName in ('Aberdeen', 'Manchester')
intersect
select
u.ID,
u.Name
from
Users as u
inner join LinkingTable as l on t.UsersID=u.ID
inner join Tags as t on t.ID=l.TagsID
where
t.TagName in ('Manager', 'Director')
答案 1 :(得分:0)
您创建的是实体属性值表。
这些非常灵活,可以在不更改数据结构的情况下将其他杂项数据存储到实体。如何开始录制喜爱的巧克力品牌,以及新的标签类型,然后将数据添加到链接表中......
然而,他们非常擅长的是搜索符合特定条件的实体(在您的情况下为用户)的数据。
这当然是可能的,这是执行此操作的一般方法,但不要指望在大量数据上有良好的性能。 (在网上搜索EAV表,优化和替代方案。)
SELECT
*
FROM
users
INNER JOIN
links
ON links.UsersId = users.id
INNER JOIN
tags
ON tags.id = links.TagsId
WHERE
tags.TagNames IN ('Aberdeen', 'Manchester', 'Manager', 'Director')
GROUP BY
users.id
HAVING
COUNT(DISTINCT CASE WHEN tags.TagOrder = 1 THEN tags.id END) >= 1
AND COUNT(DISTINCT CASE WHEN tags.TagOrder = 2 THEN tags.id END) >= 1
这只是选择符合您的任何一个搜索条件的每个 行 ,然后将其汇总到所有用户,以检查至少每个“类型”标准中的一个匹配(至少一个位置,至少一个工作角色)。
使用此方法意味着您可以相对轻松增加搜索条件的数量和复杂性。在WHERE
子句中包含所有可能的相关标记,然后分析HAVING
子句中的行组,以确保已匹配足够的 set 条件。< / p>