Sql 左连接和求和以及分组奇数行为

Sql 左连接和求和以及分组奇数行为,sql,sql-server,Sql,Sql Server,我有两张桌子: student attendance table - student_id, campus_section campus table - campus_section, number_of_students, campus_name 样本数据: Student Table: Student_Id, campus_section 1, ddr1 2, ddr1 3, ddr2 4, ddr3 5, ddv1 6, ddv2 7, ddv6 Campus Table Ca

我有两张桌子:

student attendance table - student_id, campus_section
campus table -  campus_section, number_of_students, campus_name 
样本数据:

Student Table: 
Student_Id, campus_section
1, ddr1
2, ddr1
3, ddr2 
4, ddr3
5, ddv1
6, ddv2
7, ddv6

Campus Table
Campus_Section, Number_Of_Students, Campus_Name
ddr1, 10, ddr
ddr2, 5, ddr
ddr3, 5, ddr
ddv1, 5, ddv
ddv2, 10, ddv
ddv3, 10, ddv
ddv6, 10, ddv
因此,预期的行将是

Campus, current_students, campus_students    
ddr, 4, 20
ddv, 3, 35
每个校园\u名称可以有多个校园\u节行。以下查询列出了校园名称、该校园的在校学生人数以及该校园的学生总数

select d.[campus_name] as campus_name, 
       cast(count(s.student_id) as int) as current_students, 
       sum(cast (d.[number_of_students] as int)) as campus_students 
from campus d 
left join student s 
on s.campus_section = d.campus_section  
group by d.[campus_name]
对于某些校园名称,section_students列中的结果大于此值:

select d.[campus_name] as campus_name, 
           sum(cast (d.[number_of_students] as int)) as section_students 
    from campus d 
    group by d.[campus_name]  
这意味着left join正在做某些特定行不应该做的事情。或者第二个查询可能不正确

编辑:例如,第一个查询将为某个校园名称提供18,而第二个查询将为10

有人能解释一下发生了什么事吗?这是sql server 2008

使用左join,sumcast d.[学生人数]as int将是校园中的学生人数*学生人数。通过陈述摆脱分组,你会发现原因

select d.[campus_name] as campus_name, 
       s.student_id, 
       d.[number_of_students]
from campus d 
left join student s 
on s.campus_section = d.campus_section 
因此,正确的方法是:

select d.[campus_name] as campus_name, 
       cast(count(s.student_id) as int) as current_students, 
       cast (d.[number_of_students] as int) as section_students 
from campus d 
left join student s 
on s.campus_section = d.campus_section  
group by d.[campus_name],cast (d.[number_of_students] as int)
更新 根据稍后发布的OP数据,需要先按校园分组以获得科室学生人数之和,然后加入学生表并按校园名称分组以获得当前科室学生人数

with campus_t as (select d.[campus_name] as campus_name, 
       sum(cast (d.[number_of_students] as int)) as campus_students 
     from campus d
     group by d.[campus_name])
select d.campus_name,
       d.campus_students,
       cast(count(s.student_id) as int) as current_students,
from campus_t d 
left join campus section
on section.campus_name = d.campus_name
left join student s 
on s.campus_section = section.campus_section  
group by d.campus_name,d.campus_students
注:尚未测试。请检查一下


你的问题来自非规范化设计。校园表应拆分为两个校园和校园分区表。这就是为什么我必须添加一个名为campus\u t的CTE表来获取campus实体的信息。原始校园表的数据表示校园分区实体。如果将模型规范化为三个表,那么应该更容易查询。

节可以有多个学生。因此,当连接表时,校园中的行可能会重复,如果您尝试一次性聚合所有内容,则会使结果倾斜

因此,请尝试分两步进行:首先,按校园分区计算学生人数:

SELECT
  campus_section,
  number_of_students,
  campus_name,
  COUNT(s.student_id)
FROM
  dbo.Campus AS c
LEFT JOIN
  dbo.Student AS s
ON
  c.campus_section = s.campus_section
GROUP BY
  campus_section,
  number_of_students,
  campus_name
然后按校园汇总分区结果:

SELECT
  campus_name,
  current_campus  = SUM(current_section),
  campus_students = SUM(number_of_students)
FROM
  (
    SELECT
      c.campus_section,
      c.number_of_students,
      c.campus_name,
      current_section = COUNT(s.student_id)
    FROM
      dbo.Campus AS c
    LEFT JOIN
      dbo.Student AS s
    ON
      c.campus_section = s.campus_section
    GROUP BY
      campus_section,
      number_of_students,
      campus_name
  ) AS sub
GROUP BY
  campus_name
;

你能告诉我们预期输出和实际输出吗?@SimonWhitehead我不应该发布任何数据,但我的问题中有几个输入错误,所以请重新阅读。谢谢。它不一定是实际数据,而是一个非常小的模拟样本数据。@SimonWhitehead请查看编辑。我对我的第一个查询做了一点编辑,将“大学学生”部分替换为“校园学生”。sumcast d.[大学学生人数]与校园学生人数相同,应代表该校园而非该部分的学生总数。您的方法将为每个校园名称提供多行,但我只希望每个校园有一行。我已经发布了示例数据和预期结果。