能写数据后台,需要掌握哪些进阶的sql语句?
国庆假期花了一些时间,首次尝试并玩转 grafana
,这几天继续不断优化和完善,如今看着自己的成果,相当满意。——逐步接近我想要的理想后台啦。
需求是不停歇的。今天我又给自己发掘了一些新需求,比如变量、筛选框之类,都收集下来等有空继续玩。编程学习的过程中,对于自己尚未尝试的新技能点,本能直觉会感到困难,但动手经验告诉我:莫慌,用起来就懂了,瞧我自己每次都能很快上手吖。——善于让自己在学习的过程中感受良好,并确实持续进步,自我激励是一个特别实用的软技能。
然后我想着不妨把这几天玩转 grafana
时用到的进阶版的 sql
语句整理出来。所谓进阶版,是针对我个人的 sql
能力啦,确切地讲,是指在我之前的笔记中未曾出现、且玩转 grafana 中我确实反复用到的。整理自己刚刚反复实践的新知识点,能很好地巩固新知。完成这件事,方能安心进入下一个阶段向未知冲刺。
之前写了一篇笔记,记录自己是为什么要玩 grafana ,以及如何在 24 H做到被工程师称赞,文中提及我把工程师已经实现的 sql
语句拷贝下来,拆解为元知识点,然后逐个理解:它是什么功能,如何用,然后直接用起来试试效果。
举个实例来拆解元知识点
在本篇笔记中,我也先举一个实例用作知识点拆解,如下,该述语句的作用是:统计每天具有学习行为的用户数。注:学习行为其实包含多种具体的行为,分布在两个表中。
with data as(
select
date(created_at) as time,
user_id
from user_comments
union all
select
date(created_at) as time,
user_id
from user_activities
)
select
time,
count(distinct user_id) as 每日学习用户数
from data
group by time
order by time
注意:sql 对大小写、换行、缩进之类都不敏感,这是和 python
不同的地方。上面之所以要换行和缩进,只是为了易读性。
这一条 sql 语句看着挺长,其实是两个部分。as
前面的 data 是数据的名字,我们自定义的,后面B部分的from
数据源就是它。被 with data as()
括起来的A部分,用于生成数据,相当于先做一次检索统计得到一些数据命名为 data ,然后再对 data 进行检索统计。
with data as (【语句块A】)
【语句块B】
可嵌套的 with data as()
短时间用 with data as()
用的比较多时,我就揣测:这玩意儿能嵌套吗?一试果然可行。嵌套只是让它看上去复杂点,本质没啥变化。如下所示,语句块 A 的数据源是原始数据,语句块 B 的数据源是 data,语句块 C 的数据源是 datax。
with datax as(
with data as (【语句块A】)
【语句块B】
)
【语句块C】
实战中,我最多用过3层嵌套,且偶尔为之;双层嵌套用的多一些。而单层则相当常用。
用union
合并数据行
上方实例被 with data as()
括起来的部分,其实是两个表满足条件的数据合并。抽象一下如下。
【语句块X】
union all
【语句块Y】
处理表格数据的合并时,细分有以下三个情形:
- 把多列或多行的数据,合并为单列或单行的数据
- 把A表的数列,与B表的数列合并起来
- 把A表的数行,与B表的数行合并起来
union
处理的是基于行的合并。举例来说,如果语句块X的结果为a行,语句块Y的结果为b行,则通过union all
合并后的结果将有(a+b)行。而用 union
的结果是取a和b的并集,即a、b中都存在的数据行只保留一份。
相对应的,在pandas
通过 pd.concat()
的axis
参数就能处理行、列的不同方式合并,还真是简约吖。
函数data()
与as
别名
上方举例中,语句块X 和Y大体上是蛮基础的语句。但依然出现了我之前没有用过的方法。
date(created_at) as time,
和count(distinct user_id) as 每日学习用户数
这两个片段中,as
之前是表达式语句,as
之后是该语句运算结果的别名。date()
方法是把复杂的时间数据简化为年月日的日期数据。超高频使用。count(distinct user_id)
则表示:对user_id
去重,然后统计user_id
个数。超高频使用。
类似count()
和sum()
都是高频使用的基础函数。不过数据统计中,更常用到累加。语句是定番组合,就不再单独罗列啦:
sum(兑换用户数) over (order by 兑换日期 asc rows between unbounded preceding and current row) as 累计用户数
而count(1)
,count(*)
和 count(column_name)
在不同情况下,运行效率不同。鉴于我暂时没有写出性能最好的sql语句之觉悟,暂不深究啦。
各种情况下的去重
上面提及distinct
,如何使用distinct
倒不复杂;复杂的是需求,对数据指标的定义要理解准确;不同的数据指标,对去重有不同的要求。
情境A:不去重。
虽然count的是user_id,但这个数据其实并不是每天留言的用户数,而是每天留言的条数。
select
date(created_at) as time,
count(user_id) as 每日留言条数
from
user_comments
group by
time
order by
time
情境B:当日去重。
在当天内去重,跨天不去重。用户在某一天有多条留言,最终也只能为当天留言用户数贡献计数1
select
date(created_at) as time,
count(distinct user_id) as 每日留言用户数
from
user_comments
group by
time
order by
time
情境C:历史累积去重。
有过留言行为的累计用户数,则在全时段内去重。只要该用户曾有过留言行为,则计数1,不再重复计数。
select
count(distinct user_id) as 留过言的用户总数
from
user_comments
情境D:每日和历史累积同时去重。
假设我们想知道每日新增的留言用户数,即如果该用户以前曾留言则不计数,否则在首次留言当天计数1,这个情境比前面三种复杂点,但同样相当高频使用。
with data as (
select
distinct on (user_id) user_id,
date(created_at) as time
from
user_comments
)
select
time,
count(user_id) as 每日新增留言用户数,
count(user_id) over (order by time asc rows between unbounded preceding and current row) as 累积留言用户总数
from data
group by time,user_id
order by time
几个常见的小知识点
limit
指定显示多少条数据。换言之,没有这个条件,就表示要显示查询结果的所有数据。我之前不知道这个知识点时,有时不小心直接在命令行提示符中查看某个表,会一下子打印很多很多行,以至于一直下翻都不见底……而在数据后台中,通常配合排序功能,用来显示“排行榜”数据。比如,学习次数排行榜、兑换总额排行榜之类。
select * from table_name limit 50;
order by
指定数据按哪些字段排序,默认顺序,可用desc
倒序。
select * from table_name order by column_name;
group by
指定数据按哪些字段分组,很多报表按日统计。前面举例中无形中也用了该方法数次,就不单独举例啦。
多表联合查询
最后说明下,相对复杂的多表查询。从多个表格、或表格和自定义数据源如data中合并查询。一个相对简单的实例如下,根据输入变量 user_name 从 users_extra 查询到 user_id,然后用 user_id 去user_activities 表查询。
with data as(
select user_id,user_name from users_extra where user_name = '$user_name'
)
select
count(1) as 学习行为次数
from
user_activities,data
where
user_activities.user_id = data.user_id
这种联合查询必要的条件是,多个数据源可以通过某个字段对应起来。更复杂的例子,其实都可以动用拆解的方式,拆解为更单元的知识点。这里就不展开啦。
顺便说,上面的 user_name = '$user_name'
语句是 grafana 中用于调用自定义变量,实现后可支持下拉框筛选。这也是刚开始写这篇文章时,我提到的新需求,结果文章修修改改写完,这个需求竟然被我实现了。还真是快!
小结
如果某天你和我一样开始接触一点进阶、复杂的sql语句或其它技能,千万别慌,找一些现成的实例(比如收藏我这篇笔记)来消化,逐块拆解为元知识点,然后再把它们拼装结合用起来,你会发现:也不过如此嘛。
这个过程多像玩儿积木吖!好玩好玩!
如果这篇笔记帮到了你,一定要留言告诉我吖;这将鼓励我整理和分享更多。
能写数据后台,需要掌握哪些进阶的sql语句?的更多相关文章
- MySQL高级(进阶)SQL语句
MySQL高级(进阶)SQL语句 目录 MySQL高级(进阶)SQL语句 一.实例准备--制表 1. 表1(商店区域表) 2. 表2(商店销售表) 3. 表3(城市表) 4. 表4(total_sal ...
- 在数据表中添加一个字段的SQL语句怎么写
如果要在数据表中添加一个字段,应该如何表示呢?下面就为您介绍表添加字段的SQL语句的写法,希望可以让您对SQL语句有更深的认识. 通用式: alter table [表名] add [字段名] 字 ...
- MySQL在大数据、高并发场景下的SQL语句优化和"最佳实践"
本文主要针对中小型应用或网站,重点探讨日常程序开发中SQL语句的优化问题,所谓“大数据”.“高并发”仅针对中小型应用而言,专业的数据库运维大神请无视.以下实践为个人在实际开发工作中,针对相对“大数据” ...
- Mysql:查询每个月下的数据,根据状态或者年份的sql语句
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本次的MySQL开篇记录了一道面试题,我给其扩展一下 这面试题它难点在什么地方,不外乎是操作月份和将其展示的 ...
- mysql 一张表的数据插入另一张表的sql语句
1. 表结构完全一样 insert into 表1 select * from 表2 2. 表结构不一样(这种情况下得指定列名) insert into 表(列名1,列名2,列名3) select 列 ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(十一)数据层优化-druid监控及慢sql记录
本文提要 前文也提到过druid不仅仅是一个连接池技术,因此在将整合druid到项目中后,这一篇文章将去介绍druid的其他特性和功能,作为一个辅助工具帮助提升项目的性能,本文的重点就是两个字:监控. ...
- 使用Hive或Impala执行SQL语句,对存储在HBase中的数据操作
CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...
- 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作(二)
CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...
- 【mybatis】service层中一个方法中使用mybatis进行数据库的 多个修改操作,可能是update也可能是delete操作,但是sql语句命名执行并且在控制台打印出来了,但是数据库中未更新到数据【事务的问题】
问题描述: service层中一个方法中使用mybatis进行数据库的 多个修改操作,可能是update也可能是delete操作,但是sql语句命名执行并且在控制台打印出来了,但是数据库中未更新到数据 ...
随机推荐
- CPU使用率与负载的爱恨情仇
今天有一个电话面试,面试官问我:CentOS怎么查看CPU负载?我说:看top的第一行有load average.面试官又问:为什么从这就判定是负载高呢?依据是什么呢?然后... 然后我就尴尬了,挂了 ...
- Codeforces 749E: Inversions After Shuffle
题目传送门:CF749E. 记一道傻逼计数题. 题意简述: 给一个 \(1\) 到 \(n\) 的排列,随机选取区间 \([l,r]\) 随机打乱区间内的元素,问打乱后的整个序列的逆序数期望. 题解: ...
- bootm跳转到kernel的流程
转自 https://blog.csdn.net/ooonebook/article/details/53495021 一.bootm说明 bootm这个命令用于启动一个操作系统映像.它会从映像文件的 ...
- load address、entry point、 bootm address以及kernel运行地址
load address:加载地址 load_addr mkimage -a entry point: 入口地址 entry_point mkimage -e bootm ...
- 使用SpringBoot编写Restful风格接口
一.简介 Restful是一种对url进行规范的编码风格,通常一个网址对应一个资源,访问形式类似http://xxx.com/xx/{id}/{id}. 举个栗子,当我们在某购物网站上买手机时会 ...
- 07-cmake语法-MATCHES
如果给定的字串或变量值域给定的正则表达式匹配的话,表达式返回真. IF (CMAKE_SYSTEM_NAME MATCHES "Linux") MESSAGE(STATUS &qu ...
- update mantis_bug_table
update mantis_bug_table set mantis_bug_table.original_due_date=mantis_bug_table.due_date ,) ,);
- Docker + Nginx + Tomcat 实现负载均衡简单演示
Docker + Nginx + Tomcat 实现负载均衡 环境 [root@pinyoyougou-docker ~]# docker -v Docker version 1.12.6, buil ...
- 前端页面模拟浏览器搜索功能Ctrl+F实现
<html> <head> <style type="text/css"> .res { color: Red; } .result{ back ...
- 爬虫-selenium的使用
安装 pip install selenium 开始 # coding=utf-8 from selenium import webdriver # 引用selenium库 import time # ...