sql - SAS SQL 中带有条件语句的子查询
问题描述
我正在学习在 SAS 的基本级别上使用 SQL 子查询。面对眼前的问题,我使用子查询来查询同一张表——员工信息表。本质上,我想编写一个查询来列出两个年龄组(50 岁以下和 50 岁以上)的当前员工的平均工资,这些员工的平均工资高于相应年龄组的平均工资。有一个案例 when 声明似乎是一个已被注释掉的问题。如果我只将代码用于一个年龄组,它可以正常工作,但是当我尝试同时容纳两个年龄组时,子查询会返回列的总体平均值,而不是基于员工年龄的条件平均值。谁能告诉我哪里出了问题?在 FROM 子句中使用子查询会是更好的方法吗?
proc sql;
SELECT
avg(CASE WHEN ((intck('DAY',Birth_Date,'01JAN15'd) / 365.25) < 50) THEN Salary END)
AS Under50_Age 'Under 50' format = dollar10.2,
avg(CASE WHEN ((intck('DAY',Birth_Date,'01JAN15'd) / 365.25) >= 50) THEN Salary END)
AS Over50_Age 'Over 50' format = dollar10.2
FROM orion.employee_information
WHERE Salary > (
SELECT
avg(CASE
WHEN ((intck('DAY',Birth_Date,'01JAN15'd) / 365.25) < 50) THEN Salary
/*WHEN ((intck('DAY',Birth_Date,'01JAN15'd) / 365.25) >= 50) THEN Salary*/
END)
FROM orion.employee_information
WHERE
Employee_Term_Date IS missing)
AND Employee_Term_Date IS missing;
quit;
解决方案
您正在旋转查询中的数据。自然的 SQL 分组聚合是每个 BY 组一行,您的选择试图从不同的 BY 组创建不同的列。
自然查询结果不需要子查询。使用 case 语句创建分组依据的分类值。计算该组的平均工资。
收入高于平均工资的两个年龄组(50 岁以下和 50 岁以上)的当前员工的平均工资
典型的方法是在计算的分类 ( age_group
) 上连接两个嵌套查询。
例子:
嵌套查询类似,第一个别名为group_computation
,第二个别名为all
。两个嵌套查询都会计算 age_group 并将自己限制为活跃的员工。
使用streaminit
例程和rand
函数是希望无论 SAS 安装如何创建的数据都是相同的。
data have;
call streaminit(123);
do empid = 1 to 1000;
birth_date = intnx('YEAR', '01JAN15'd, -18 - rand('unif', 51)) - rand('unif',365);
if ranuni(123) < 0.15 then
term_date = intnx("year", birth_date, 18 + rand('unif', 30));
else
term_date = .;
salary = round(1000 * (30 + rand('unif', 75)),25);
output;
end;
format birth_date term_date yymmdd10.;
run;
proc sql;
select
group_computation.age_group
, mean(all.salary) as avg_of_above_average_salaries format=dollar10.
, count(*) as cnt_of_above_average_salaries
, group_computation.avg_salary
, group_computation.emp_count as avg_salary_count
from
(
select
case
when round(intck('DAY',Birth_Date,'01JAN15'd) / 365.25, 0.0001) < 50 then 'under 50'
else 'over 50'
end
as age_group
, mean (salary) as avg_salary format = dollar10.
, count(*) as emp_count
from
have
where
term_date is missing
group by
age_group
) as group_computation
join
(
select
case
when round(intck('DAY',Birth_Date,'01JAN15'd) / 365.25, 0.0001) < 50 then 'under 50'
else 'over 50'
end
as age_group
, salary
from
have
where
term_date is missing
) as all
on
group_computation.age_group = all.age_group
where
all.salary > group_computation.avg_salary
group by
group_computation.age_group, group_computation.avg_salary, group_computation.emp_count
;
quit;
产生一个结果集
avg_of_above_ cnt_of_above_
average_ average_ avg_salary_
age_group salaries salaries avg_salary count
-------------------------------------------------------------------
over 50 $88,201 164 $68,984 328
under 50 $85,851 261 $66,519 546
推荐阅读
- python - 如何执行多个进程以异步计算值并在完成后收集结果?
- sql-server - 在 ASP 经典 SQL 查询中使用特殊字符
- python - Python。发生异常:IndexError。列表索引超出范围
- c++ - 引用和指向数组的指针有何不同,哪一个更可取?
- asp.net-core-webapi - 使用 NSwag.AspNetCore 和 AddOpenApiDocument 的示例请求
- python - 在 Firestore 集合组上运行 != 查询
- node.js - 如何将 typescript 与 openfaas 处理程序一起使用?
- python-3.x - 如何快速从 python 列表中删除重复项?
- r - 在 r 中使用 scale_color_manual 手动分配颜色
- video - jitsi meet如何实现负载均衡?