具有多个子查询的SQL查询

时间:2018-01-17 11:38:54

标签: sql

构建基于标签的内部电话簿并创建了一个链接表,但无法看到如何加入选择所有来自阿伯丁和曼彻斯特的经理和导演的人。

用户

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是一项艰难的任务,任何想法,都要提前感谢。

2 个答案:

答案 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>