将多个SELECT查询合并为一个

时间:2015-09-06 14:33:54

标签: sql oracle oracle11g

正如标题所说,查询需要组合多个选择查询。问题如下:

显示员工总数,以及1995,1996,1997,1998中雇用的员工总数。

我的查询:

select (select count(*) from employees) as "Total",
       (select count(*) from employees where hire_date between 'JAN-1-0095' and 'DEC-1-0095')as "1995",
       (select count(*) from employees where hire_date between 'JAN-1-0096' and 'DEC-1-0096') as "1996",
       (select count(*) from employees where hire_date between 'JAN-1-0097' and 'DEC-1-0097') as "1997",
       (select count(*) from employees where hire_date between 'JAN-1-0098' and 'DEC-1-0098') as "1998" 
from employees

但问题是,只返回单个记录,而是对表中的所有记录执行此查询,从而产生以下输出:

enter image description here

3 个答案:

答案 0 :(得分:3)

您可以使用条件计数:

select count(*) as total_count, 
       count(case when extract(year from hire_date) = 1995 then 1 end) as "1995",
       count(case when extract(year from hire_date) = 1996 then 1 end) as "1996",
       count(case when extract(year from hire_date) = 1997 then 1 end) as "1997",
       count(case when extract(year from hire_date) = 1998 then 1 end) as "1997",
from employees;

这利用了聚合函数忽略NULL值这一事实,因此count()只计算case表达式返回非空值的那些行。

您的查询为employees表中的每一行返回一行,因为您不应用任何分组。每个select都是一个标量子选择,可以为employees表中的每一行执行。

如果您将最终的from employees替换为from dual可以使其仅返回一行 - 但您仍然会计算每个子行中的所有行-select。

您还应该像您一样避免隐式数据类型转换。 'JAN-1-0095'是一个字符串,根据您的NLS设置隐式转换为date。如果从我的计算机执行,您的查询将无法运行(因为NLS设置不同)。

当你正在寻找一整年时,只需比较年份就可以更短,更容易理解(至少在我看来)。

另一个选择是使用正确的日期文字,例如使用Oracle的where hire_date between DATE '1995-01-01' and DATE '1995-12-31'函数to_date()或更加冗长:where hire_date between to_date('1995-01-01', 'yyyy-mm-dd') and to_date('1995-12-31', 'yyyy-mm-dd')

答案 1 :(得分:0)

假设这些年份确实是你想要的,你的查询的问题是你从employees中选择,所以你得到每一行。你可以使用:

select (select count(*) from employees) as "Total",
       (select count(*) from employees where hire_date between 'JAN-1-0095' and 'DEC-1-0095')as "1995",
       (select count(*) from employees where hire_date between 'JAN-1-0096' and 'DEC-1-0096') as "1996",
       (select count(*) from employees where hire_date between 'JAN-1-0097' and 'DEC-1-0097') as "1997",
       (select count(*) from employees where hire_date between 'JAN-1-0098' and 'DEC-1-0098') as "1998" 
from dual;

我会使用date '1998-01-01'作为日期常量。

但是,我更喜欢@ a_horse_with_no_name的解决方案。

答案 2 :(得分:0)

您应该避免使用大量子查询。你应该试试这个:

SQL Server:

select distinct
a.id_clients,a.name,
case when b.id_clients_action=2 then b.date_action else null end as date
from clients a
left join clients_action b on a.id_user_created=b.id_user_created

在ORACLE中

SELECT count(*) as Total, hire_date 
FROM employees
WHERE year(hire_date) IN ('1995','1996','1997','1998') 
GROUP BY hire_date WITH CUBE

除了GROUP BY生成的小计之外,CUBE扩展还会为每个hire_date生成小计。