带有计数和分组的内部联接

时间:2016-06-06 11:26:44

标签: tsql count group-by aggregate-functions

我有2张桌子

时间表:
pupil_id,staff_id,subject,lesson_id

Staff_info:
staff_id,姓氏

时间表表格包含1000行,因为每个学生的ID都列在他们每个期间。

我想列出所有老师的名字,以及他们所做的课程数量(计数)。所以我必须用DISTINCT进行SELECT。

SELECT DISTINCT TIMETABLE.STAFF_ID,
                COUNT(TIMETABLE.LESSON_ID),
                STAFF.SURNAME
FROM STAFF
INNER JOIN TIMETABLE ON TIMETABLE.STAFF_ID = STAFF.STAFF_ID
GROUP BY TIMETABLE.STAFF_ID

然而我收到错误:

  

专栏' STAFF.SURNAME'在选择列表中无效,因为它不是   包含在聚合函数或GROUP BY子句中。

4 个答案:

答案 0 :(得分:5)

这应该做你想要的:

SELECT s.STAFF_ID, COUNT(tt.LESSON_ID),
       s.SURNAME
FROM STAFF s INNER JOIN
     TIMETABLE tt
    ON tt.STAFF_ID = s.STAFF_ID
GROUP BY s.STAFF_ID, s.SURNAME;

注意:

  • 除非两个表格中都有重复项,否则您不需要DISTINCT。这种数据结构似乎不太可能,但如果一名工作人员可以有两个相同的课程,你可以使用COUNT(DISTINCT tt.LESSON_ID)
  • 表别名使查询更易于编写和阅读。
  • 您应该在STAFF.SURNAME以及ID <。li>中加入GROUP BY
  • 我倾向于从表格中取STAFF_ID列作为主键。
  • 如果您希望没有课程的工作人员,您可以将INNER JOIN更改为LEFT JOIN

答案 1 :(得分:1)

SELECT T.STAFF_ID,
       T.CNT,
       S.SURNAME
FROM STAFF S
JOIN (
    SELECT STAFF_ID, CNT = COUNT(/*DISTINCT*/ LESSON_ID)
    FROM TIMETABLE
    GROUP BY STAFF_ID
) T ON T.STAFF_ID = S.STAFF_ID

答案 2 :(得分:1)

另一种选择:

SELECT DISTINCT si.staff_id, surname, COUNT(lesson_id) OVER(PARTITION BY staff_Id)
FROM Staff_info si
INNER JOIN Timetable tt ON si.staff_id = tt.staff_id 

答案 3 :(得分:1)

在Select列的列表中使用Aggregate函数(Count,Sum,Min,Max,Avg)时,GROUP BY部分中也应该提到Select列列表中但不在聚合函数中的任何其他列。因此,您需要更改您的查询,并将STAFF.SURNAME添加到GROUP BY部分:

SELECT TIMETABLE.STAFF_ID,
            COUNT(TIMETABLE.LESSON_ID),
            STAFF.SURNAME
FROM STAFF
INNER JOIN TIMETABLE ON TIMETABLE.STAFF_ID = STAFF.STAFF_ID
GROUP BY TIMETABLE.STAFF_ID,STAFF.SURNAME

在你的场景中,区别也没用。并且当您要显示教师姓名和计数课程时,您不需要将TIMETABLE.STAFF_ID添加到选择列的列表中,但它应保留在分组依据部分以防止重复名称。

SELECT COUNT(TIMETABLE.LESSON_ID),
            STAFF.SURNAME
FROM STAFF
INNER JOIN TIMETABLE ON TIMETABLE.STAFF_ID = STAFF.STAFF_ID
GROUP BY TIMETABLE.STAFF_ID,STAFF.SURNAME

您可能需要查看this W3C post以获取更多信息