结构化数据中的存在判断问题
1. 外键映射的存在性检测在两个表中,根据外键映射的存在性查找记录。【例 1】 统计一班男生的平均分。成绩表和学生表如下:
【解题思路】从分数表选出数据时,判断是否存在班级的名称是一班且学生性别是男性的记录,如果存在则选出。【SPL 脚本】AB1=connect("db")/连接数据库2=A1.query("select * from Score")/查询学生表3=A1.query("select * from Student")/查询学生成绩表4=A3.select(Class=="Class 1" && Gender=="Male")/选出一班男生5=A2.join@i(Class:StudentID, A4:Class:ID)/使用函数 A.join@i() 连接过滤6=A5.groups(StudentID; avg(Score):Score)/分组汇总每个学生的平均分A6的执行结果如下:StudentIDScore176374……当外键表数据量大时,可以使用游标的有序归并来解决。【例 2】 查询 2014 年每月没有使用折扣的订单数量。订单表和订单明细表如下:
【解题思路】从订单表选出数据时,判断是否存在折扣为 0 的订单,如果存在则选出。【SPL 脚本】AB1=connect("db")/连接数据库2=A1.cursor("select * from Order where year(Date)=2014 order by ID")/创建订单表游标,选出 2014 年记录3=A1.cursor("select * from Detail order by ID")/创建订单明细表游标4=A3.select(Discount==0)/选出没有使用折扣的记录5=joinx(A2:Order,ID;A4:Detail,ID)/使用函数 joinx 对订单表和订单明细表的游标进行有序归并6=A5.groups(month(Order.Date):Month; icount(Order.ID):OrderCount)/分组汇总每个月的订单数量A6的执行结果如下:MonthOrderCount116225……2. 非等值连接的存在性检测在一个表中,通过非等值连接的存在性检测查找数据。【例 3】 查询同一订单跨度超过一年的订单的销售额。订单表部分数据如下:IDNUMBERAMOUNTDELIVERDATEARRIVALDATE108141408.02014/01/052014/04/18108142204.02014/02/212014/04/05108143102.02014/03/142014/04/06108144102.02014/04/092014/04/27108145102.02014/05/042014/07/04108481873.02014/01/062014/04/21……………【解题思路】从订单表中选出数据时,判断订单跨度超过一年的记录是否存在,如果存在则选出。【SPL 脚本】AB1=connect("db")/连接数据库2=A1.query("select * from Detail")/查询订单明细表3=A2.group(ID)/按订单日期分组4=A3.select(interval(~.min(DELIVERDATE), ~.max(ARRIVALDATE)) > 365)/选出同一订单的时间间隔超过 365 天的记录5=A4.new(ID, ~.sum(AMOUNT):Amount)/创建数据表,统计每个订单的销售额A5的执行结果如下:IDAmount109986800.0110134560.01103220615.0……3. 外键映射的不存在性检测在两个表中,根据外键映射的不存在性检测查找记录。【例 4】查询所有科目均高于 80 分的学生。成绩表和学生表如下:
【解题思路】从学生表选出数据时,判断学生是否存在任意科目低于 80 分的成绩,如果不存在则选出。【SPL 脚本】AB1=connect("db")/连接数据库2=A1.query("select * from Student")/查询学生表3=A1.query("select * from Score")/查询成绩表4=A3.select(Score<=80)/选出成绩不高于 80 分的记录5=A4.id(StudentID)/按学生 ID 去重6=A2.join@d(ID, A5)/使用函数 A.join@d() 选出不匹配的记录A6的执行结果如下:IDClassName2Class 1Ashley16Class 2Alexis4. 双重否定的存在性检测通过双重否定,查询能够匹配的记录。【例 5】 查询选修了所有课程的学生。选课表、课程表和学生表如下:
【解题思路】从学生表选出数据时,判断学生是否存在某一科目课程没有选出的记录,如果不存在则选出。处理双重否定的存在性检测时,我们也可以正向思考,只要选出选修科目数量与所有科目数量相同的记录即可。【SPL 脚本】AB1=connect("db")/连接数据库2=A1.query("select * from Student")/查询学生表3=A1.query("select * from Course")/查询课程表4=A1.query("select * from SelectCourse")/查询选课表5=A4.groups(StudentID; icount(CourseID):CourseCount)/选课表按照学生 ID 分组汇总每个学生的选课数量6=A5.select(CourseCount==A3.len())/选出选择了所有课程的学生 ID7=A2.join@i(ID, A6:StudentID)/使用函数 A.join@i() 连接过滤A7的执行结果如下:IDNameClass4Emily SmithClass 15. 任意条件的存在性检测在两个表中,根据任意条件的存在性检测查找记录。【例 6】 查询两科分数差超过 30 分的学生。成绩表和学生表如下:
【SQL 语句】从学生表选出数据时,判断是否存在有任意两个科目成绩相差 30 分的记录,存在则选出。【SPL 脚本】AB1=connect("db")/连接数据库2=A1.query("select * from Student")/查询学生表3=A1.query("select * from Score")/查询成绩表4=A3.group(StudentID)/成绩表按学生 ID 分组5=A4.select(~.max(Score)-~.min(Score)>30)/选出最高分和最低分相差超过 30 分的学生6=A5.id(StudentID)/按学生 ID 去重7=A2.join@i(ID,A6)/使用函数 A.join@i() 连接过滤A7的执行结果如下:IDNameClass4Emily SmithClass 18MeganClass 1………6. 全部条件的存在性检测根据一个表中数据,筛选出满足所有条件的记录。【例 7】查询哪些员工的工资比所有销售部员工都要高。员工表部分数据如下:IDNAMEDEPTSALARY1RebeccaR&D70002AshleyFinance110003RachelSales90004EmilyHR70005AshleyR&D16000…………【SQL 语句】从员工表选出数据时,判断员工工资大于所有销售部员工工资的记录是否存在,存在则选出。【SPL 脚本】AB1=connect("db")/连接数据库2=A1.query("select * from Employee")/查询员工表3=A2.select(DEPT:"Sales").max(SALARY)/选出所在城市包含在一线城市中的记录4=A2.select(SALARY>A3)/分组汇总各部门的平均工资A4的执行结果如下:IDNAMEDEPTSALARY5AshleyR&D1600020AlexisAdministration1600022JacobR&D1800047ElizabethMarketing17000《SPL CookBook》中还有更多相关计算示例。