图解面试题:如何找到破产玩家?
【题目】
下表是一个玩家某天的游戏对局时间记录以及破产记录。现在要分析出当天连续破产玩家人数,这里的连续破产概念是连续两次记录为1就算。有什么思路来判断小表中的a用户是破产玩家?
玩家ID:上表只给了a玩家,表中还有其他玩家;
对局开始时间:时间类型,游戏是每一时间开一局,所以看到玩家a的对局开局时间是9点、10点、11点等这样;
是否破产:0代表未破产,1代表破产
【解题思路】
“连续两次记录”,可以先将任意两次对局结果连接起来,然后找出符合连续条件的记录。一个表里是无法找到两次对局结果的,怎么办?
可以用交叉连接,就可以返回任意两次对局结果。
1. 交叉连接
首先我们来复习一下《猴子 从零学会sql》里讲过的交叉连接(corss join)。
如下图,是对表“text”自身进行交叉联结的结果:它将会返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积。
本题的对局表交叉连接结果如下
select * from 对局表 as A cross join 对局表 as B;
这个交叉连接的结果可以看作左边是表A,右边是表B。
2.找出连续时间
在交叉联结的结果中,下图红色框中的每一行数据,左边是“当前时间”数据,右边是“连续时间”的数据。比如第一个红色框中左边是“9:00”(当前时间),右边是“10:00”(连续时间)。
选出上图中的“A.对局开始时间比B.对局开始时间小一小时
题目要求,破产条件是:连续两次记录为1就算。换成能听懂的话,就是同时满足下面两个条件:
(1)因为游戏是每一时间开一局,所以“连续两次记录“就是:
表A中的“对局开始时间” - 表B中的“对局开始时间” = -1
(2)表A中的“否破产值“=1,表B中的“否破产值“=1
先来看第一个条件如何实现?
本表中的“对局开局时间”为时间类型,我们需要从中提取小时,需要用到时间提取的函数
extract (unit from date) 当unit分别为year(年份), month(月份), day(日期), hour(小时), minute(分)等。
例如:select extract (hour from '9:00') as 小时
9点和10点相差1小时
extract (hour from '9:00')-select (extract (hour from '10:00')
=-1
对应条件1中的 表A中的“对局开始时间” - 表B中的“对局开始时间” = -1 就是:
( extract(hour from A.对局开始时间) - extract(hour from B.对局开始时间) )=-1
在交叉联结的查询结果中加上where条件来筛选出符合条件1的数据
当我们要对连接结果进行筛选时,使用on语句。因此加入上一步的交叉连接结果如下:
select *from 对局表 as A cross join 对局表 as Bwhere (extract(hour from A.对局开始时间) - extract(hour from B.对局开始时间)) = -1;
得到结果:
3. 破产结果相同为1 的数据
前面说到破产条件2是:
表A中的“否破产值“=1,表B中的“否破产值“=1
在上面查询语句中加入where子句来筛选数据:
where A.是否破产=1 and B.是否破产=1
最终的sql语句就是:
select *from 对局表 as A cross join 对局表 as Bwhere (extract(hour from A.对局开始时间) - extract(hour from B.对局开始时间)) = -1 and A.是否破产=1 and B.是否破产=1;
查询结果如下:
因此得到a是破产玩家。
如果题目换成表中多少破产玩家?
在上面的sql已经得到了哪些玩家是破产玩家,只需要统计查询结果的表行数就可以了,例如上面的查询结果表看作表c,破玩家数量就是:
select count(*)from c;
【本题考点】
1.考察逻辑思维能力,如何将“连续”条件拆解为可以具体的问题。可以使用逻辑树分析方法将复杂问题拆解成一个个可以解决的子问题。
2.考查多表联结以及交叉联结:当我们需要两个表中任意两行数据结合时,需要用交叉连接方式。
【举一反三】
编写一个 SQL 查询,查找所有连续出现两次的数字。
参考答案:
select a.numfrom 数字 as a cross join 数字 as bwhere a.ID=b.ID +1 and a.num=b.num;
得到结果:
- objective-C中的序列化(serialize)与反序列化(deserialize)
- 微信小程序 template 模板功能实现循环
- ASP.NET Web API 接口执行时间监控
- 这么多前端优化点你都记得住吗?
- 愚蠢的”记住“密码方式终于还是出了问题
- C#获取本机可用端口
- 想知道你的对象用微信和谁聊得最多吗?一个代码告诉你
- objective-C中的接口与泛型
- 段永朝:天性,互联网的灵性回归
- objective-C中的Class(类类型),Selector(选择器SEL),函数指针(IMP)
- 数据中心进水了怎么办?数据中心如何防洪?
- 戴若犁:虚拟中的现实
- kvm虚拟化管理平台WebVirtMgr部署-完整记录(1)
- objective-C中如何判断一个类中有没有定义某个方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法