MySQL习题:
第一题
虽然这道题是中等题,但是当你捋清表与表之间的关系和你所想要的目标字段时就会发现这道题并不是想象那么难,有时候表中给的数据越多越方便我们去计算结果,或比一些我们自己去新创一些字段更加简单,理清思路的你就会发现表三Items表就是个障眼表。
我的思路:看到输出结果表的字段,应该要清楚这些字段要从哪些表找出来。首先,看到buyer_id和join_date就明白这是表一的字段,orders_in_2019是需要根据题目要求对表二进行条件过滤得到的结果,然后将表一和表二用left join外连接起来得到我们所要的答案。第二步我们需要构思表二的条件怎么去筛选正确结果,首先是判断订单order日期,我用substring去截取日期首四位,然后判断其是否为2019,再根据筛选结果用group by和count去计算得到第三个字段。最后外连接后,对字段进行修饰一下即可。代码如以下所示:
select user_id as buyer_id ,join_date,if(num>0,num,0) as orders_in_2019
from Users u
left join
(select buyer_id,count(order_id) as num
from Orders
where substring(order_date,1,4) =2019
group by buyer_id
order by buyer_id asc) o
on u.user_id =o.buyer_id;
对此,我也去看了别人的思路,基本大同小异,这一步用时间格式输出订单的年份,其他大致差不多,就不再赘述了。大家可以自行了解一番。
select a.user_id as buyer_id,a.join_date,
ifnull(count(case when date_format(b.order_date,'%Y') = '2019' then 1 end),0) as orders_in_2019 from
Users a left join Orders b on a.user_id = b.buyer_id
group by a.user_id
第二题
这道题表与表之间的逻辑还是比较简单,它考察的是对MySQL的count和round函数使用熟悉度。
round函数的基本用法如下图所示,其他函数在以后可以慢慢向大家介绍:
题目代码如下图所示:
select contest_id ,
round(count(distinct user_id)/(select count(*) from Users)*100,2) as percentage
from Register
group by contest_id
order by percentage desc,contest_id asc;
第三题
这道题看起来好像挺简单的,但是里面还是含有一些坑的。
刚开始我是这么写的:
select product_id, min(year) as first_year, quantity, price
from sales
group by product_id;
然后运行结果的是对的,也符合刚开始的案例结果输出,我就对我的SQL语句逻辑就放松警惕了。
当我提交的时候,就开始报错了
我一直认为是数据的问题,比如其中一些数据的年份超过2024年,再后来改了我把2024年后的数据给排掉了,发现还在不断地报错,一直在错的道路越走越远。直到后面我去看了我的代码,用min(year)整合数据,我错认为有了min()整合函数,我想要的数据会排到第一条,但是发现后面quantity和price字段是以group by的第一条为准。
但后面换了一种思路,这张Sales表以product_id、min(year)为主键,并且信息唯一不重复,就可以筛选符合条件的product_id、min(year)两个字段,再以子查询去让Sales再去判断一次。具体代码如以下所示:
select
product_id,
year as first_year,
quantity,
price
from sales
where (product_id, year) in
(select product_id, min(year)
from sales
group by product_id)
总结:
1、不要看太多表就太怕,捋清表与表的关系,明白我们想要的字段在哪张表,该怎么去计算。
2、不要钻牛角尖,不要想当然,要及时返回来看一看自己当初的脚步是否错误!
3、要清楚明白MySQL一些函数的使用,比如聚合函数、流程函数等等。
Java习题(递归):
递归算法:
可以用一个例子让大家更熟悉一下:
以下是代码底层执行流程,大家也可点击教学链接:
其实例子并不难,主要难的是学会理解递归的思想,看完上一个例子大家也可看看这个。
个人觉得这猴子吃桃这个例子是一道函数题。分析前一天和后一天的桃子关系,列出式子f(x)=2*f(x-1)+1+1,x代表的是第几天,f(x)代表第几天的桃子,然后式子不断的递归循环得出结果。具体代码如下:
public static int f(int num){
if(num>1){
return 2*f(num-1)+2;
}else {
return 1;
}
}
辛苦大家看完以上的内容,当你看到这一步基本对递归有了更加深入的了解,但可以接下来继续去感受递归的魅力,大家可以看看接下来的啤酒问题,大家可以思考片刻,再看看具体代码。还是得重申一遍,难得不是代码,是递归思想的本身!
案例:啤酒问题
啤酒问题:啤酒2元一瓶,四个盖子可以换 一瓶,2个空瓶子可以换一瓶,请问n块钱可以喝多少瓶?
public class BeerQuestion {
public static void main(String[] args) {
demo1(10,0,0,0);
}
public static void demo1(int m, int j, int kp, int gz){
while (m>=2){
m-=2; //m代表钱
j++; //j代表喝完的酒
kp++; //kp代表空瓶子
gz++; //gz代表空盖子
}
while (kp>=2){
kp-=2;
j++;
kp++;
gz++;
}
while (gz>=4){
gz-=4;
j++;
kp++;
gz++;
}
if (kp<2 && gz<4){
System.out.println("一共喝了"+ j+ "瓶酒,剩余"+ kp+"个空瓶,"+ gz+ "个盖子");
}else {
demo1(m,j,kp,gz);
}
}
}
这个代码总体来说非常的丝滑简洁,代码的思想就是三种换酒情况:我有两块钱我就去买酒喝,然后留下瓶盖和酒瓶;我瓶盖够了我继续换酒喝;我瓶子够了也继续去换酒喝。最后进行条件判定,如果瓶盖和瓶子不够了就结算喝了多少瓶,否则继续递归换酒喝。哈哈哈哈哈哈这对爱喝酒的人是一件美事,但我想说一句,敬酒虽好,可不要贪杯哟。后期如果有时间跟大家介绍一下用二分查找法和递归算法结合的题目,感谢大家的阅读,最后一句祝大家国庆快乐呀!