sql datetime比较大小_SQL做题小技巧

数据分析必学必会当属SQL取数,毕竟要分析首先需要有数嘛。

sql的语法教程往上一搜就有很多,本文主要将介绍几个sql小技巧,灵活用上技能做对大部分的笔试题。

由于很多笔试是在牛客网上完成的,所以本文主要是用sqlite3的语法(实际上不同sql的区别主要只是在日期函数为主等函数上的差异)。

1. with as 的使用

    with as主要是为了代码简洁美观,易读易懂。主要用于创建临时表,便于此后的查询。

    比如现在有个表是用户消费表trade_tb,字段有user_id, trade_time, amount, 现在想统计找出哪一个用户的消费金额最高,并输出其消费金额。

    如果不用with as创建临时表,sql如下:

select user_id, max(total_amount) from (  select user_id, sum(amount) as total_amount  from trade_tb  group by user_id)  b-- 或者select user_id, sum(amount) as total_amountfrom trade_tbgroup by user_idorder by sum(amount) desclimit 1

上述写法可能在其他sql中不能运行,但在sqlite3中可以。一般来说,可能会通过下面的sql查询得到。

select user_id, total_amountfrom (  select user_id, sum(amount) as total_amount  from trade_tb  group by user_id)  aorder by total_amount desclimit 1;

由于中间的代码其实就是计算每个用户的总金额,可以提取成临时表,

with total_amount_tb as(    select user_id, sum(amount) as total_amount     from trade_tb     group by user_id)select user_id, total_amountfrom total_amount_tb order by total_amount desclimit 1;

with as 结构主要在代码涉及到多个临时表或者多重子查询时使用。【没有想到比较合适的例子,下次再补充】

2. 条件语句的使用

在sqlite3中,条件语句一般通过case when实现,在新版本的sqlite3中也有iif函数实现,不过笔试的平台一般版本没这么新,不支持iif函数。

假如现在有学生期末成绩表score_tb,字段为stu_id, course, score,假设每个学生每门课仅有一次考试成绩。现在想取出每个学生的语文、数学、英语考试成绩。

a23525e7e4a820e234a3ef3d2e8f1985.png

select stu_id,       sum(case course when '语文' then score else null end) as 语文成绩,       max(case course when '数学' then score else null end) as 数学成绩,       avg(case course when '英语' then score else null end) as 英语成绩from score_tbgroup by stu_id;

e87131dcd13cb6c8ccecdb82b7cc5813.png

这里,由于限制了每个学生在每门课上至多有一次成绩,所以用上聚合函数sum()/max()/min()/avg()的结果都是一致的。

3. 窗口函数的使用

窗口函数一般可以为排序类的函数rank()/dense_rank()/row_number(),也可以为sum()/avg()等聚合函数。

一般的笔试题目可以通过使用排序类的函数来简化实现。

查询消费总额第3的用户:

bce22f19fcfed7c952eb2b8adda147e0.png

with total_amount_tb as(    select user_id, sum(amount) as total_amount     from trade_tb     group by user_id),total_amount_rank_tb as(    select user_id,            total_amount,           rank() over (order by total_amount desc) as rnk    from total_amount_tb)select user_id, total_amountfrom total_amount_rank_tbwhere rnk = 3;

0c53b50231aac01e40236b9e82fcbfdc.png

取出每门成绩前2的学生及其对应的成绩:

with score_rank_tb as(    select stu_id,            course,           score,           rank() over (partition by course order by score desc) rnk    from score_tb)select course, score, stu_id, rnkfrom score_rank_tbwhere rnk <= 2order by course

747a0180bba1a43f4705194462cadfd7.png

另外,注意区分rank()/dense_rank()/row_number()的区别:

ac4eb96d507abc56ef9213c55a4beb0e.png

select stu_id,       course,       score,       rank() over (partition by course order by score desc) rnk,       dense_rank() over (partition by course order by score desc) dense_rnk,       row_number() over (partition by course order by score desc) row_numfrom score_tb2

3df654599c6c02f7cb0ed5d2a76d1343.png

也就是可以看到,对于成绩相同的排序,rank()和dense_rank()取的是相同的名次,但是对于下一个成绩,rank()是累加前面的总人数得到下一个名次,而dense_rank()是累加前面的数字个数得到的下一个名次,而row_number()则表示行数,根据排序的结果给每一行标注行号。

4. 日期时间函数的使用

sql的题目有时会出现一些需要通过日期函数表达的,这时候就会出现很多问题,因为不同的sql时间函数存在一些差异,特别是sqlite3的日期函数跟其他sql差别比较大,所以为了做好笔试题,一般还得提前把日期函数复习一遍。

  • 从字符串生成日期

select datetime('2020-01-01 00:12:34'),       date('2020-01-01 00:12:34'),       time('2020-01-01 00:12:34');

3f979933138adc46b7893195f85e04f7.png

  • 从unix时间戳生成日期

select datetime(0,'unixepoch'),       date(0,'unixepoch'),       time(0,'unixepoch');

7ca691f618994c8c6d9a1ed9869bf23e.png

select datetime(0,'unixepoch','utc'),       date(0,'unixepoch','utc'),       time(0,'unixepoch','utc');-- 可以看出这里假设0的我们当地的时间戳,转成日期之后,再转换成utc的时间。

470e4bb169b6419fa4fde9076529aff7.png

select datetime(0,'unixepoch','localtime'),       date(0,'unixepoch','localtime'),       time(0,'unixepoch','localtime');-- 由于有localtime的转换,所以这里0假设的是utc的时间。

c9eb6236a8443a74b0185edbb554c777.png

  • 从日期转换成其他形式的值

strftime(format, timestring)实际上就是将日期转换成其他表示形式。

select strftime('%Y-%m-%d %H:%M:%S','2020-01-02 04:15:36') as 日期时间,       strftime('%f','2020-01-02 04:15:36') as 带小数点的秒,       strftime('%j','2020-01-02 04:15:36') as 一年第几天,       strftime('%J','2020-01-02 04:15:36') as 从JulianDay至今天数,       strftime('%s','2020-01-02 04:15:36') as 从19700101至今秒数;

4da3f38aedc5562b908b957be570ad97.png

  • 日期加减

select datetime('now') as 当前,        datetime('now','start of month') as 月初,       datetime('now','start of month','+1 month','-1 day') as 月底,       datetime('now', '+20 days') as 二十天后,       datetime('now','+50 hours') as 五十小时后,       datetime('now', 'start of year') as 年初,       datetime('now', 'start of day') as 今天起始

f33e438c641a08ca13b0c70e7f4049aa.png

25f11f64eb3fcae5484032a5d1deafc2.png

掌握这些小技巧其实笔试题就能做大部分啦~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值