0

我有一个具有此设置的 mysql 数据库(省略与此问题无关的字段)

users
  id                #primary key

user_group_teachers
  id                #primary key
  teacher_id        #foreign key to users.id
  user_group_id     #foreign key to users_groups.id

user_groups
  id                #primary key

user_group_members
  id                #primary key
  pupil_id          #foreign key to pupils.id
  user_group_id     #foreign key to users_groups.id

pupils
  id                #primary key

我在一个名为“user_ids”的数组中有一组用户 ID。

对于这些用户 ID 中的每一个,我想通过

user -> user_group_teachers -> user_groups -> user_group_members -> pupils

协会。即,跨表的某种连接。

所以,我想得到一些行看起来像的结果

[1, [6,7,8,9]]

其中 1 是教师 ID,[6,7,8,9] 是学生 ID。我只希望每个学生 ID 在第二个列表中出现一次。

谁能告诉我如何在尽可能少的查询中做到这一点(或者,更广泛地说,尽可能高效)。我可能通常在 user_ids 中有 1000 到 10,000 个 id。

我在 ruby​​ 脚本中执行此操作,因此可以在查询之间将结果存储为变量(数组或散列),如果这会使事情变得更简单。

谢谢!Lyhan 的最大编辑

Lyhan - 谢谢,但您的解决方案似乎不起作用。例如在结果的第一行,使用你的方法,我有

| user_id | group_concat(pupils.id separator ",")                                                                         
|       1 | 2292   

但是,如果我以较慢的一步一步的方式获得相关的学生 ID,那么我会得到不同的结果:

select group_concat(user_group_teachers.user_group_id separator ",") 
from user_group_teachers 
where user_group_teachers.teacher_id = 1 
group by user_group_teachers.teacher_id;

我明白了

| group_concat(user_group_teachers.user_group_id separator ",")  
| 12,1033,2117,2280,2281   

将这些值(user_group ids)插入另一个查询:

select group_concat(user_group_members.pupil_id separator ",") 
from user_group_members 
where user_group_members.user_group_id in (12,1033,2117,2280,2281) 
group by user_group_members.user_group_id;

我明白了

| group_concat(user_group_members.pupil_id separator ",") 
| 47106,47107  

感谢 group_concat 方法顺便说一句,这很方便:)

4

2 回答 2

1

我在上面做了几条对解决方案很重要的评论,但我认为你可以从这两个查询开始,看看它是否能让你走得更远,得到你需要的东西。

要为所有组的学生获取教师的有序列表,您可以执行以下操作:

select distinct t.teacher_id, m.pupil_id
from user_groups g
    inner join user_group_teachers t
        on t.user_group_id = g.id
    inner join user_group_members m
        on t.user_group_id = g.id
order by t.teacher_id, m.pupil_id

要为与小组关系密切的学生获取教师的有序列表,您可以执行以下操作:

select g.id, t.teacher_id, m.pupil_id
from user_groups g
    inner join user_group_teachers t
        on t.user_group_id = g.id
    inner join user_group_members m
        on t.user_group_id = g.id
order by g.id, t.teacher_id, m.pupil_id

您必须遍历这些结果集并将它们转换为嵌套数组,但这是您想要的数据。

更新:更新:如果数据集太大或者您不想遍历单个结果集,那么您可以这样做来模拟上面第一个查询的结果并根据查询结果集构建子数组:

/* Use this query to drive the batch */
select distinct t.teacher_id
from user_groups_teachers t
order by t.teacher_id

/* Inside a loop based on first query result, pull out the array of pupils for a teacher */
select distinct m.pupil_id
from user_groups_members m
    inner join user_groups g
        on g.id = m.user_group_id
    inner join user_groups_teachers t
        on t.user_group_id = g.id
where t.teacher_id = /* parameter */
order by m.pupil_id
于 2013-11-07T16:37:44.757 回答
0

这就是我想出的:

    select pupil_group_teachers.teacher_id, group_concat(pupil_group_members.pupil_id separator ',') 
    from pupil_group_teachers join pupil_groups on pupil_group_teachers.pupil_group_id = pupil_groups.id
    join pupil_group_members on pupil_group_members.pupil_group_id = pupil_groups.id
    group by pupil_group_teachers.teacher_id;

它似乎有效,而且速度非常快。Lyhan(后来删除了他的答案)和 David Fleeman 都帮我弄清楚了。干杯,伙计们。

于 2013-11-07T17:39:37.573 回答