【问题标题】:SQL - Return 0 value for a groupingSQL - 为分组返回 0 值
【发布时间】:2019-03-18 16:32:41
【问题描述】:

我有 3 个表,Member_School 保存成员和学校之间的链接,Schools 包含学校信息,Category 是完整类别名称(成员类别)的简单查找表。

我试图获取每所学校的所有成员类别的计数,但对于特定学校没有成员的类别,我无法获得 0 计数。到目前为止,这是我的查询:

WITH MemberNums AS
(
SELECT School_No, Category, COUNT(Member_No) AS NumberOfMembs

FROM Member_School

WHERE Finish_Date > GETDATE()

AND Category IS NOT NULL

GROUP BY School_No, Category

)


SELECT School.School_No, Category.Category, MemberNums.NumberOfMembs AS NumberOfMembs, School.School_Name, School.ATH_No, School.AWA_No, School.CLE_No, School.CYC_No, School.CYF_No, School.OBS_No, School.PEN_No, School.RHI_No, 
School.STA_No, School.SYL_No

FROM School 

INNER JOIN MemberNums 
ON School.School_No = MemberNums.School_No

LEFT JOIN Category
ON Category.Category_No = MemberNums.Category

ORDER BY School_No

因此,例如,此查询可能返回 ID 为 123 的学校的 8 行,但类别表中有 10 个类别。我想要得到的是每所学校 10 行,计算每个类别中有多少成员(包括在 Member_School 表中没有特定类别记录的学校的零计数)

以下是每个表的示例行:

类别:

Category_No: Cat1
Category: Category1

学校:

School_No: 123
School_Name: Highschool
Memb_No: 10
Secondary: True
Job_No: XJI314
ATH_No: 1
AWA_No: 1
CLE_No: 1
CYC_No: 1
CYF_No: 1
OBS_No: 1
PEN_No: 1
RHI_No: 1
STA_No: 1
SYL_No: 1

Member_School:

Rec_No: 1
Member_No: 2
School_No: 123
Start_Date: 2018-03-19 00:00:00.000
End_Date: 2020-03-19 00:00:00.000
Category: Cat1

【问题讨论】:

  • 你试过LEFT JOIN memberNums吗?
  • 哪个 dbms? SQL 只是多个 dbms 供应商使用的一种语言。
  • 听起来您想要一个介于 SchoolsCategory 之间的 cross join,这样您就可以获得每个学校的每个类别。然后使用Member_School 获取每个学校/类别对的成员数量(如果有)。
  • 我不明白你在做什么。您提到了计数,但您的查询与计数没有任何相似之处。
  • @GordonLinoff 计数在 MemberNums CTE 中完成

标签: sql tsql


【解决方案1】:

如果您想要零,则使用cross join 生成行,然后引入现有数据:

select s.School_No, c.Category, count(ms.School_No) as NumberOfMembs as NumberOfMembs,
       s.School_Name, s.ATH_No, s.AWA_No, School.CLE_No,
       s.CYC_No, s.CYF_No, s.OBS_No, s.PEN_No, s.RHI_No, 
       s.STA_No, s.SYL_No
from school s cross join
     categories c left join
     Member_School ms
     on ms.School_No = s.School_No and
        ms.Category = c.Category_No and
        ms.Finish_Date > getdate()
group by s.School_No, c.Category, 
         s.School_Name, s.ATH_No, s.AWA_No, School.CLE_No,
         s.CYC_No, s.CYF_No, s.OBS_No, s.PEN_No, s.RHI_No, 
         s.STA_No, s.SYL_No;

【讨论】:

  • 这并没有完全解决我的问题,但重构和使用交叉连接有效
【解决方案2】:

使用左连接

WITH MemberNums AS
(
SELECT School_No, Category, COUNT(Member_No) AS NumberOfMembs

FROM Member_School

WHERE Finish_Date > GETDATE()

AND Category IS NOT NULL

GROUP BY School_No, Category

)    

SELECT School.School_No, Category.Category, MemberNums.NumberOfMembs AS NumberOfMembs, School.School_Name, School.ATH_No, School.AWA_No, School.CLE_No, School.CYC_No, School.CYF_No, School.OBS_No, School.PEN_No, School.RHI_No, 
School.STA_No, School.SYL_No

FROM School 

left JOIN MemberNums 
ON School.School_No = MemberNums.School_No

LEFT JOIN Category
ON Category.Category_No = MemberNums.Category

ORDER BY School_No

【讨论】:

  • 您好,我尝试使用左连接,但它不起作用,仍然获得例如第一所学校的 8 个类别,第二所学校的 6 个类别,依此类推。
  • @hjalpmig 您能否提供示例数据和预期输出,或者您可以使用您的数据创建小提琴链接,这将有助于解决您的问题
  • Adadin Tuhin 用数据示例更新问题。
【解决方案3】:

您是否尝试过使用右外连接?使用正确的外部连接和合并函数来确保显示 0 而不是 null。 我在下面发布了一个示例查询

WITH MemberNums AS
(
SELECT School_No, Category, COUNT(Member_No) AS NumberOfMembs

FROM Member_School

WHERE Finish_Date > GETDATE()

AND Category IS NOT NULL

GROUP BY School_No, Category

)


SELECT School.School_No, Category.Category, COALESCE(MemberNums.NumberOfMembs, 0) AS NumberOfMembs, School.School_Name, School.ATH_No, School.AWA_No, School.CLE_No, School.CYC_No, School.CYF_No, School.OBS_No, School.PEN_No, School.RHI_No, 
School.STA_No, School.SYL_No

FROM School 

INNER JOIN MemberNums 
ON School.School_No = MemberNums.School_No

RIGHT OUTER JOIN Category
ON Category.Category_No = MemberNums.Category

ORDER BY School_No

如果您想要来自 school 和 member_school 的所有可能没有类别的结果,那么您可能需要考虑 FULL OUTER JOIN

【讨论】:

  • 嗨,右外连接和全外连接仍然没有给我每个学校的 10 个类别
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 2014-09-14
  • 1970-01-01
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
相关资源
最近更新 更多