目录
一、了解joins
二、笛卡尔积
三、PROC SQL按照以下步骤处理联接
四、内联接
1、功能:
2、两种方法
3、语法:
4、举例:
是一种查询,被联接的表不需要具有相同的行数或者列数。
联接一般有两种类型:
内联接——取两个表公共的部分外联结概念:处理任何类型的联接时,proc sql首先生成一个笛卡尔积,其中包含来自所有表中行,在一起的所有的可能的组合。
生成一个笛卡尔积:如果在from语句中指定多个表,但没有where语句,则proc sql 将返回表的笛卡尔积。
注意:
在笛卡尔积中,第一个表中的每一行与第二个表中的每一行组合在一起
具有公共名称的列不会被覆盖
笛卡尔积中的行数等于提供数据的表中的行数的乘积
当您运行涉及无法优化的笛卡尔产品的查询时,PROC SQL将以下警告消息写入SAS日志:NOTE: The execution of this query involves performing one or more Cartesian product joins that cannot be optimized.
在许多情况下,PROC SQL可以优化联接的处理,从而最小化生成笛卡尔产品所需的资源。
举例:
work.one work.two x a x b --------------------------------------- 1 A 2 x 2 B 3 y 3 D 5 v
cartesian product x a x b ----------------------- 1 A 2 x 1 A 3 y 1 A 5 v 2 B 2 x 2 B 3 y 2 B 5 v 3 D 2 x 3 D 3 y 3 D 5 v
从指定的表中构建行的笛卡尔积
基于WHERE语句中指定的联接条件以及任何其他子设置条件(on语句),计算笛卡尔积中的每一行,并删除不满足指定条件的任何行
如果指定了汇总函数,则汇总符合条件的行
返回要在输出中显示的行
将两个表之间匹配的行组合在一起,又称为:常规联接
指定要在FROM语句中连接的两个表,子句由INNER JOIN关键字分隔。通过ON子句,指示应该如何匹配行
根据在WHERE子句中指定的匹配条件连接这两个表
from:指定第一个表,指定联接类型(INNER JOIN),指定第二个表
on:指定联接条件(连接条件中比较的列需要具有相同的数据类型,否则proc sql 不会执行连接)
table:源表的名称
<other clauses>:可选的proc sql子句
SELECT column-1<,...column-n> FROM table-1 | view-1 INNER JOIN table-2| view-2 <INNER JOIN...table-n | view-n> ON table1.column=table2.column <other clauses>;使用带有INNER JOIN关键字的FROM子句
proc sql; select * /*列名分别为:x a x b*/ from work.one inner join work.two on one.x=two.x; quit; /*消除重复的列*/ proc sql; select one.x, a, b /*列名分别为:x a b*/ from work.one inner join work.two on one.x=two.x; quit; proc sql; select one.*, b /*列名分别为:x a b*/ from work.one inner join work.two on one.x=two.x; quit; proc sql; select one.x as ID, two.x, a, b /*列名分别为:ID x a b*/ from work.one inner join work.two on one.x=two.x; quit;
联接具有匹配值的行的表 work.three work.four x a x b --------------------------------------- 1 A1 2 x1 1 A2 2 x2 2 B1 3 y 2 B2 5 v 4 D
proc sql; select * from work.three inner join work.four on three.x=four.x; quit;输出结果: x a x b ----------------------- 2 B1 2 x1 2 B2 2 x2 2 B1 2 x1 2 B2 2 x2
关键字AS用于在FROM子句中定义表别名
proc sql; title 'Employee Names and Job Codes'; select staffmaster.empid, lastname, firstname, jobcode from certadv.staffmaster inner join certadv.payrollmaster on staffmaster.empid=payrollmaster.empid; quit; proc sql; title 'Employee Names and Job Codes'; select s.empid, lastname, firstname, jobcode from sasuser.staffmaster as s inner join sasuser.payrollmaster as p on s.empid=p.empid; quit;一下两种情况,会使用as关键字: 1、表与自身链接(自连接或自反连接) from sasuser.staffmaster as s1,sasuser.staffmaster as s2 2、需要引用不同库中相同名称的表中的列 from certadv.flightdelays as af,certadvf.flightdelays as wf on af.delay > wf.delay
复杂的PROC SQL内部连接
/* 创建一个报告,其中显示居住在纽约的所有员工的姓名,包括姓名的首字母和姓(R. Long)、工作代码和年龄。报告还应该按照工作代码和年龄进行排序。 sasuser.Staffmaster----EmpID, LastName, FirstName, State sasuser.Payrollmaster--EmpId, JobCode, DateOfBirth */ proc sql outobs=15; title 'New York Employees'; select substr(firstname,1,1) || '. ' || lastname as Name, jobcode, int((today() - dateofbirth)/365.25) as Age from sasuser.payrollmaster as p inner join sasuser.staffmaster as s on p.empid = s.empid where state='NY' order by 2,3 ; quit;SELECT子句使用函数和表达式创建两个新列
PROC SQL内部连接与摘要函数
/* 总结了每个工作代码中针对纽约员工的列:员工数量和平均年龄 sasuser.Staffmaster----EmpID, LastName, FirstName, State sasuser.Payrollmaster--EmpId, JobCode, DateOfBirth */ proc sql outobs=15; title 'Average Age of New York Employees'; select jobcode,count(p.empid) as Employees, avg(int((today() - dateofbirth)/365.25)) format=4.1 as AvgAge from sasuser.payrollmaster as p inner join sasuser.staffmaster as s on p.empid= s.empid where state='NY' group by jobcode order by jobcode; quit;
