对 4 个表的 SQL 查询:非常复杂?

发布于 2024-12-01 10:16:04 字数 253 浏览 1 评论 0原文

我有四个表

alert:
    * monitor_id
    * group_id

group:
    * group_id

user:
    * user_id
    * email

user_group:
    * group_id
    * user_id

是否可以仅使用 monitor_id 来获取用户的邮件? 如果是!是否可以只在一个查询中进行? 请帮助我无论是通过sql查询还是通过主义!

i have four tables

alert:
    * monitor_id
    * group_id

group:
    * group_id

user:
    * user_id
    * email

user_group:
    * group_id
    * user_id

is it possible to have the user's mail using just the monitor_id ?
if yes! is it possible in only one query?
please help me whether by the sql query or the doctrine !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

肥爪爪 2024-12-08 10:16:04

正确的查询:

SELECT DISTINCT user.email FROM user 
inner join user_group on user.user_id=user_group.user_id 
inner join alert on  alert.group_id=user_group.group_id
where alert.monitor_id = provided_monitor_id

上一个带有 Shahbaz 评论的查询。

SELECT * FROM user inner join user_group on user.user_id=user_group.user_id 
inner join  group on user_group.group_id=group.group_id inner 
join alert on  alert.group_id=group.group_id
group by user.user_id

编辑(作者:Shahbaz):为了帮助解释该命令的工作原理:

当您有两个表共享一个字段(如果您愿意,可以是一个变量)时,您可以 join 这两个表(也称为 inner join),从而产生一个更大的表,合并两个表中的数据(如果没有共享字段,您甚至可以这样做)。让我们通过一个例子来了解一下:

表 People:字段:pid、pname、pjob,

其中包含条目

  • (0, 'Alice', 'Student')
  • (1, 'Bob', '工厂工人')
  • (2, 'clara', '护士')

表工作:字段:jname,jpay,

包含条目

  • ('老师',1000)
  • ('学生',0)
  • ('工厂工人', 2000)

现在,如果您说 People join Jobs 您会得到一个包含 9 个条目的表,其中包含:

字段:pid、pname、pjob、jname、jpay,

其中条目为

  • (0、'Alice'、'student'、 '老师', 1000)
  • (0, '爱丽丝', '学生', '学生', 0)
  • (0, '爱丽丝', '学生', '工厂工人', 2000)
  • (1, '鲍勃', '工厂工人', '老师', 1000)
  • (1, '鲍勃', '工厂工人', '学生', 0)
  • (1, '鲍勃','工厂工人','工厂工人',2000)
  • (2,'克拉拉', '护士', '老师', 1000)
  • (2, '克拉拉', '护士', '学生', 0)
  • (2, '克拉拉', '护士', '工厂工人', 2000)

正如你所看到的还不是这么好的桌子!您可以使用join 中的on 条件来提取彼此相关的信息。例如,我们可能想查看每个人的工资。因此,People.pjob 应该等于 Jobs.jname,因此,如果您说 People join Jobs on People.pjob=Jobs.jname 您会得到一个表,其中包含:

字段:pid、pname、pjob、jname , jpay

包含条目

  • (0, 'Alice', '学生', '学生', 0)
  • (1, '鲍勃', '工厂工人', '工厂工人', 2000)

请注意,Clara 的工作不存在于 Jobs 表中,因此她不存在于最终表中。

虽然内连接为您提供来自两个匹配表的数据,但您可能希望获取表的数据,即使另一端没有匹配的数据。这称为外连接。在此示例中,People 外连接 Jobs 生成一个包含字段的表

:pid、pname、pjob、jname、jpay,

其中条目为

  • (0, 'Alice', 'student', 'student', 0)
  • (1 , '鲍勃', '工厂工人', '工厂工人', 2000)
  • (2, '克拉拉', '护士', null, null)
  • (null, null, null, 'teacher', 1000)

如果您只想要表即使不匹配,也要包含 outer join 的左侧,请使用 left external join (在这种情况下,将出现“Clara”行,而不是“teacher”行) ' 排)。同样,右外连接会给出右表中的行(即使不匹配),但不会给出左表中的行。

最后,您必须已经知道 select 的作用,它只是返回一个表,其中包含从提供的列中选择的列(* 选择所有列)。给定的表可以只是表的名称,也可以是使用 sql 命令形成的任何其他表(使用 select 命令本身创建的表(在这种情况下,请毫不犹豫地使用括号),使用加入命令等)。如果您了解 SQL 的递归性质,您就可以创建任意复杂的命令。想象一下,表上的每个操作都会生成另一个表,您可以简单地与其他操作结合使用,就好像该表是一个简单的存储命名表一样!

Right query:

SELECT DISTINCT user.email FROM user 
inner join user_group on user.user_id=user_group.user_id 
inner join alert on  alert.group_id=user_group.group_id
where alert.monitor_id = provided_monitor_id

Previous one with Shahbaz comments.

SELECT * FROM user inner join user_group on user.user_id=user_group.user_id 
inner join  group on user_group.group_id=group.group_id inner 
join alert on  alert.group_id=group.group_id
group by user.user_id

Edit (by Shahbaz): To help explain how the command works:

When you have two tables sharing a field (a variable if you like), you can join the two tables (also called inner join), resulting in a bigger table combining the data from the two tables (you could even do it if there are no sharing fields). Let's go through this with an example:

Table People: fields: pid, pname, pjob

with entries

  • (0, 'Alice', 'Student')
  • (1, 'Bob', 'factory worker')
  • (2, 'clara', 'nurse')

Table Jobs: fields: jname, jpay

with entries

  • ('teacher', 1000)
  • ('student', 0)
  • ('factory worker', 2000)

Now if you say People join Jobs you get a table with 9 entries, having:

fields: pid, pname, pjob, jname, jpay

with entries

  • (0, 'Alice', 'student', 'teacher', 1000)
  • (0, 'Alice', 'student', 'student', 0)
  • (0, 'Alice', 'student', 'factory worker', 2000)
  • (1, 'Bob', 'factory worker', 'teacher', 1000)
  • (1, 'Bob', 'factory worker', 'student', 0)
  • (1, 'Bob', 'factory worker', 'factory worker', 2000)
  • (2, 'Clara', 'nurse', 'teacher', 1000)
  • (2, 'Clara', 'nurse', 'student', 0)
  • (2, 'Clara', 'nurse', 'factory worker', 2000)

As you can see this is not such a good table! You can use the on condition in join to extract information that are relevant to each other. For example, we may want to see the pay of each people. Therefore, the People.pjob should equal to Jobs.jname so, if you say People join Jobs on People.pjob=Jobs.jname you get a table having:

fields: pid, pname, pjob, jname, jpay

with entries

  • (0, 'Alice', 'student', 'student', 0)
  • (1, 'Bob', 'factory worker', 'factory worker', 2000)

Note that Clara's job didn't exist in Jobs table and thus she is not present in the final table.

While inner join gives you data from the two tables that match, you may want to get data of the tables even if there is no matching on the other side. This is called outer join. In this example People outer join Jobs yields a table having

fields: pid, pname, pjob, jname, jpay

with entries

  • (0, 'Alice', 'student', 'student', 0)
  • (1, 'Bob', 'factory worker', 'factory worker', 2000)
  • (2, 'Clara', 'nurse', null, null)
  • (null, null, null, 'teacher', 1000)

If you want only the table on the left side of the outer join to be included even if unmatched, use left outer join (in this case, the 'Clara' row will be present and not the 'teacher' row). Likewise, right outer join gives rows from the right table even if unmatched, but not the left table.

Finally, you must already know what select does, it simply returns a table with selected columns from the provided column (* selecting all columns). The given table could be just the name of a table, or any other table formed with sql commands (tables created with select command itself (in which case don't hesitate to use parenthesis), tables create with join command etc). If you understand this recursive nature of SQL, you can create commands as complicated as you like. Just imagine that each operation on tables, yields another table that you can simply use in conjunction with other operations as if that table was a simple stored named table!

清晨说晚安 2024-12-08 10:16:04

如果您想使用 Monitor_id 获取用户电子邮件,请执行以下操作:

SELECT DISTINCT
  u.user_id
  u.email
FROM `user` u
INNER JOIN user_group ug ON u.user_id = ug.user_id 
INNER JOIN `group` g ON ug.group_id = g.group_id 
INNER JOIN alert a ON a.group_id = g.group_id
WHERE a.monitor_id = '1548'

因为从 Monitor_id 到 user.email 的路径会遍历所有表,所以您将需要所有这些联接。
只要您对连接中使用的所有字段都建立了索引(!),运行时应该会很快。

If you want to use the monitor_id to get a users email then do:

SELECT DISTINCT
  u.user_id
  u.email
FROM `user` u
INNER JOIN user_group ug ON u.user_id = ug.user_id 
INNER JOIN `group` g ON ug.group_id = g.group_id 
INNER JOIN alert a ON a.group_id = g.group_id
WHERE a.monitor_id = '1548'

Because the path from monitor_id to user.email goes through all the tables, your will need all those joins.
As long as you have indexed (!) all fields used in the joins the runtime should be fast.

夜雨飘雪 2024-12-08 10:16:04

另一种方法(不使用DISTINCTGROUP BY):

SELECT 
    u.user_id
  , u.email
FROM `user` AS u
WHERE EXISTS
      ( SELECT *
        FROM alert AS a 
          JOIN `group` AS g
            ON g.group_id = a.group_id 
          JOIN user_group AS ug
            ON ug.group_id = g.group_id
        WHERE ug.user_id = u.user_id 
          AND a.monitor_id = @monitorId      -- the monintor_id to be checked
      ) 

注意:使用关键字或保留字命名的表或字段不是一个好习惯用户,甚至更糟糕的

Another way (not using DISTINCT or GROUP BY):

SELECT 
    u.user_id
  , u.email
FROM `user` AS u
WHERE EXISTS
      ( SELECT *
        FROM alert AS a 
          JOIN `group` AS g
            ON g.group_id = a.group_id 
          JOIN user_group AS ug
            ON ug.group_id = g.group_id
        WHERE ug.user_id = u.user_id 
          AND a.monitor_id = @monitorId      -- the monintor_id to be checked
      ) 

Note: it's not good practice to have tables or fields named with keywords or reserved words like user and even worse group.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文