Oracle 如果使用GROUPBY子句没有行返回,select语句应将count返回为零

Oracle 如果使用GROUPBY子句没有行返回,select语句应将count返回为零,oracle,Oracle,我有一个学生信息表,它有“状态”列,状态可以是p(出席)、a(缺席)、S(生病)、T(转学)、L(左) 我期待的预期产出如下 状态计数(*) 第12页 S1 A 2 t0 l0 但产出如下所示: 状态计数(*) 第12页 S1 A 2 我们需要针对状态T和L的行以及计数为零的行,尽管数据库中不存在任何记录。您应该将您的状态存储在某个位置(在另一个表中)。否则,使用子查询列出它们: with stored_statuses as ( select 'P' code, 'present' d

我有一个学生信息表,它有“状态”列,状态可以是p(出席)、a(缺席)、S(生病)、T(转学)、L(左)

我期待的预期产出如下

状态计数(*)
第12页
S1
A 2
t0
l0
但产出如下所示:

状态计数(*)
第12页
S1
A 2

我们需要针对状态T和L的行以及计数为零的行,尽管数据库中不存在任何记录。

您应该将您的状态存储在某个位置(在另一个表中)。否则,使用子查询列出它们:

with stored_statuses as (
  select 'P' code, 'present' description from dual
  union all 
  select 'A' code, 'absent' description from dual
  union all 
  select 'S' code, 'ill' description from dual
  union all 
  select 'T' code, 'transfer' description from dual
  union all 
  select 'L' code, 'left' description from dual
)
select ss.code, count(*) from student_info si
left join stored_statuses ss on ss.code = si.status
group by ss.code

@mkuligowski的方法很接近,但是您需要在CTE之间建立一个外部连接,提供所有可能的状态值,然后您需要计算实际匹配的条目:

-- CTE to generate all possible status values
with stored_statuses (status) as (
            select 'A' from dual
  union all select 'L' from dual
  union all select 'P' from dual
  union all select 'S' from dual
  union all select 'T' from dual
)
select ss.status, count(si.status)
from stored_statuses ss
left join student_info si on si.status = ss.status
group by ss.status;

STATUS COUNT(SI.STATUS)
------ ----------------
P                    12
A                     2
T                     0
S                     1
L                     0
CTE充当一个虚拟表,其中包含要计数的五种状态。然后,外部联接到实际表中-外部联接意味着即使不存在匹配项,CTE中的行仍然包括在内-然后统计表中匹配的行。这允许包含零计数

您也可以通过集合执行此操作:

select ss.status, count(si.status)
from (
  select column_value as status from table(sys.odcivarchar2list('A','L','P','S','T'))
) ss
left join student_info si on si.status = ss.status
group by ss.status;
最好有一个包含这些值(及其描述)的物理表;然后还可以使用主键/外键关系来强制现有表中允许的值


如果所有状态值实际上都出现在表中,但您有一个过滤器恰好排除了其中某些行的所有行,那么您可以从表本身获取所有(已使用)值的列表,而不是对其进行硬编码

如果您的初始查询是这样的,带有一个完全组合的筛选器:

select si.status, count(*)
from student_info si
where si.some_condition = 'true'
group by si.status;
然后,您可以使用子查询从未筛选的表中获取所有不同的值,从该表到同一个表进行外部联接,并将筛选器作为外部联接条件的一部分应用:

select ss.status, count(si.status)
from (
  select distinct status from student_info
) ss
left join student_info si on si.status = ss.status
and si.some_condition = 'true'
group by ss.status;

它不能作为
where
子句保留(至少在这里,它应用于外部联接的右侧),因为这将覆盖外部联接,并有效地将其转换回内部联接。

您是否有一个包含所有状态值的表?不,它是同一个表student\u info中的一个字段。那么您是如何认识您的(仅限于)需要这五种状态吗?这是该表中唯一不同的状态。@罗杰-但它们不都在表中-否则您会看到它们的计数为非零。或者您正在筛选(可能是在日期范围内),并且这些其他状态存在,但仅在筛选出的行上?在您的问题中包含您当前的查询和示例数据会很有帮助。我想使用where子句,它应该放在这个查询中的什么位置。@罗杰-在
左join
子句之后和
group by
子句之前。对于外部联接条件,它可能需要是一个
,而不是一个单独的
where
子句,以阻止它返回内部联接。。。所以所有的状态值实际上都存在于表中,它们只是被遗漏了,因为它们恰好被
where
子句排除了?