真的需要优化我的SQL:使用N-N表选择每行的所有外行

问题描述 投票:3回答:3

我有一个N-N表,举个例子教师和主题:

有一个Teacher表如下:

    +---------------+-----------------------+
    |    Id         | Name                  |
    +---------------+-----------------------+
    | 1             | John Williams         |
    | 2             | Erika Miller          |
    +---------------+-----------------------+

有一个Subject表如下:

    +---------------+-----------------------+
    |    Id         | Name                  |
    +---------------+-----------------------+
    | 1             | Music                 |
    | 2             | Art                   |
    | 3             | Languages             |
    | 4             | Geography             |
    +---------------+-----------------------+

并且有一个TeacherTeachesSubject如下:

    +---------------+-----------------------+
    |  TeacherId    |        SubjectId      |
    +---------------+-----------------------+
    | 1             | 1                     |
    | 1             | 2                     |
    | 1             | 3                     |
    | 2             | 3                     |
    | 2             | 4                     |
    +---------------+-----------------------+

只有每个表有超过10000个条目。

我需要创建一个查询,返回给我这样的东西:

+---------------+-----------------------+
|    Teacher    | SubjectsOfThatTeacher |
+---------------+-----------------------+
| John Williams | Music, Art, Languages |
| Erika Miller  | Languages, Geography  |
+---------------+-----------------------+

我现在正在做的是:

  1. SELECT * FROM Teachers;
  2. 将结果保存在数组中。
  3. 在每个循环中迭代执行此查询的数组: SELECT Name FROM Subjects inner join "everything" WHERE TeacherTeachesSubject.TeacherId = actualteacherid;
  4. 将结果保存为String,用逗号分隔。

每次我想从表中选择所有数据时,我都会进行10000次查询。

你知道如何有效地开展这项工作吗?我真的不需要逗号,我只需要它在String中作为String在HTML列中显示。

sql sql-server
3个回答
5
投票

使用SQL Server 2017,使用STRING_AGG()

SELECT t.Name, STRING_AGG(s.Name, ', ') SubjectsOfThatTeacher
FROM Teacher t
INNER JOIN TeacherTeachesSubject tts ON tts.TeacherId = t.Id
INNER JOIN Subject s ON s.Id = tts.SubjectId
GROUP BY t.Id, t.Name

4
投票

对于pre-SQL Server 2017,有FORXML and STUFF hack:

SELECT t.Name, SubjectsOfThatTeacher = STUFF(
                                   (SELECT ',' + s.Name 
                                    FROM TeacherTeachesSubject tts 
                                    INNER JOIN Subject s ON s.Id = tts.SubjectId
                                    WHERE tts.TeacherId = t.Id
                                    FOR XML PATH(''))
                                    ,1,1,'')
FROM Teacher t
GROUP BY t.Id, t.Name

0
投票

对于SQL Server 2017之前使用GROUP_CONCAT聚合。可在Github上获得

Download GROUP_CONCAT

© www.soinside.com 2019 - 2024. All rights reserved.