用于 MySQL 的语法 下列 SQL 语句把 “Persons” 表中的 “P_Id” 列定义为 auto-increment 主键:
CREATE TABLE Persons ( P_Id int NOT NULL AUTO_INCREMENT, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), PRIMARY KEY (P_Id) )订单表格的客户id = 客户表格的客户id
CREATE TABLE Orders ( Id_O int NOT NULL, OrderNo int NOT NULL, Id_P int, PRIMARY KEY (Id_O), FOREIGN KEY (Id_P) REFERENCES Persons(Id_P) );mysql中删除表记录delete from和truncate table的用法区别: MySQL中有两种删除表中记录的方法: (1)delete from语句, (2)truncate table语句。
delete from语句可以使用where对要删除的记录进行选择。delete语句更灵活。 truncate table将删除表中的所有记录。
情况一:清空表中的所有记录,可以使用下面的两种方法: delete from tablename truncate table tablename 其中第二条记录中的table是可选的。
情况二:删除表中的部分记录,只能使用delete语句。 delete FROM table1 WHERE ;
参考
执行顺序 1. from 2. join 3. on 4. where 5. group by 6. having 7. select 8. distinct 9. order by正则表达式参考1 案例:匹配手机号码
select phone_num from table where REGEXP_LIKE(phone_num, '^[1]{1}[35678]{1}[0-9]{9}$'); # 可替代为[[:digit:]]{9}^、$:代表字符开始与结束 {n}:字符数字出现n次
比如在计算全部产品总价格时,订单单价 乘 订单数+库存数,需要注意可能存在空值,要替换为0.
SELECT ProductName,UnitPrice*(UnitsInStock+IFNULL(UnitsOnOrder,0)) FROM Products现定义一table名为output,其中定义两个column分别为monthid(var型)和sale(number型),若sale值=1000时翻译为D,=2000时翻译为C,=3000时翻译为B,=4000时翻译为A,如是其他值则翻译为Other:
Select monthid , decode (sale,1000,'D',2000,'C',3000,'B',4000,'A',’Other’) sale from output;sign()函数根据某个值是0、正数还是负数,分别返回0、1、-1, 用如下的SQL语句取较小值:
select monthid,decode(sign(sale-6000),-1,sale,6000) from output;in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。如果查询的两个表大小相当,那么用in和exists差别不大。如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in。
例题:使用含有关键字exists查找未分配具体部门的员工的所有信息。
select * from employees as e where not exists (select emp_no from dept_emp where emp_no = e.emp_no);返回每个部门下面的员工,用逗号
select dept_no,group_concat(emp_no SEPARATOR ',') from dept_emp group by dept_no;如果是从后往前,则为单参数 substr(var_string, -3),倒数三个
相同点:
都是对数据进行过滤,只保留符合条件的有效数据不同点:
having是从前面筛选的字段里再筛选,where是从数据表中的字段直接筛选的where是不能用字段的别名,having可以(由于where是直接筛选的,所以别名是不能用的,比如下面的where avg(price)是不合法的) select id, avg(price) as ag from goods **where ag > 100** group by goods_category; # 不合法类型的区别 where是一个约束声明(E.G. 比如数据库的分区字段),在查询的结果返回之前对查询条件进行约束,并且后面不能写“聚合函数”。
having是一个过滤声明,在查询的结果返回之后对查询条件进行约束,并且后面可以写“聚合函数”。
聚合函数:sum, min, max, avg, count
在from后面的执行顺序:可以协助判断是否先约束还是后过滤(where先进行条件的约束,之后再进行聚合函数的计算,得到结果返回之后用having进行筛选):where > 聚合函数 > having
用法是一样的,都是在函数之后接上 over (已排序的字段) row_number是对每一行数据进行序号标记(无重复),而rank是对每一行进行序号标记但是允许同个水平是同一个序号(有重复)。
select row_number() over(order by var_x desc) as row_num, * from table;参考1 参考2
PV表a(表结构为user_id,goods_id),点击表b(user_id,goods_id),数据量各为50万条,在防止数据倾斜的情况下,写一句sql找出两个表共同的user_id和相应的goods_id
数据倾斜描述的是Map-Reduce中,由于存在空值 key 的分布严重不均匀,导致的很多数据交给了一个reduce,而剩下的少部分到了不同的reduce处理。所以在reduce方面可能卡在了99%
原因:
join两个大表,存在大量的null值,这些都在一个reduce里面处理函数 distinct 处理大表,遇到较多的特殊值group by的维度过小,某些reducer处理速度较慢合并的表格的字段,存在着不同的类型——int或者字符,hash会自动地将int作为若干个group,而字符汇成一个group如何调优:
join 操作中,使用 map join 在 map 端就先进行 join让小表 join 大表,使得小表先进内存大表 join 大表的过程中,把空值的 key 用随机数附在字符串后面,把倾斜的数据分到不同的reducer上。在用count distinct 的过程中,用group by 来代替1)Hadoop原理:采用HDFS(Hadoop Distributed File System)分布式存储文件,MapReduce分解计算,其它先略 2)MapReduce原理:
a. map阶段:读取HDFS中的文件,解析成<k,v>的形式,并对<k,v>进行分区(默认一个区),将相同k的value放在一个集合中 b. reduce阶段:将map的输出copy到不同的reduce节点上,节点对map的输出进行合并、排序
———————————————— 版权声明:本文为博主「稻蛙」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u013382288/article/details/80450360
有两个表A 和B ,均有key 和value 两个字段,如果B 的key 在A 中也有,就把B 的value 换为A 中对应的value 这道题的SQL 语句怎么写?
update b set b.value=(select a.value from a where a.key=b.key) where b.id in(select b.id from b,a where b.key=a.key);下面的例子是,btype表示奖金类型,如果是1,则奖金为工资乘以10%,是2,则奖金为工资乘以20%,以此类推到else,最后再接上end。
SELECT e.emp_no, e.first_name, e.last_name, b.btype, s.salary, (CASE b.btype WHEN 1 THEN s.salary * 0.1 WHEN 2 THEN s.salary * 0.2 ELSE s.salary * 0.3 END) AS bonus FROM employees AS e INNER JOIN emp_bonus AS b ON e.emp_no = b.emp_no INNER JOIN salaries AS s ON e.emp_no = s.emp_no AND s.to_date = '9999-01-01'中位数
--没有考虑偶数的情况 set @mm = (select count(*)/2 from table); select var_1 from table order by var_1 limit @mm, 1; --考虑偶数的情况 set @i = -1; select avg(t.var_1) from (select @i := @i + 1 as ii, var_1 from table order by var_1) as t where t.ii in (floor(@i/2), ceiling(@i/2));众数
select var_2, count(*) as cnt from table group by var_2 having count(*) >= select max(cnt) from (select count(*) as cnt from table group by var_2);升级版中位数 三个班级合在一起的一张成绩单,统计每个班级成绩中位数 解:设表table中字段为id,class,score
select t1.class, avg(distinct t1.score) as median from table t1, table t2 on t1.id = t2.id group by t1.class, t1.score having sum(case when t1.score >= t2.score then 1else 0 end) >= (select count(*)/2 from table where table.class = t1.class) and having sum(case when t1.score <= t2.score then 1else 0 end) >= (select count(*)/2 from table where table.class = t1.class);———————————————— 版权声明:本文为博主「稻蛙」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u013382288/article/details/80450360
字段及表说明: 表名:user_log 字段名: log_day:登录日期 device_id:用户设备id app_id:用户app的id,其中device_id和app_id确定唯一的用户
连字符:var1 || var2
select log_day, count(user_day1) / count(user_day0) as retention1 count(user_day3)/count(user_day0) as retention3 from ( select a.log_day, a.user_day0, b.device_id || b.app_id user_day1, c.device_id || c.app_id user_day3 from (select log_day, device_id || app_id user_day0 from user_log tmp1 where device_id || app_id not in (select distinct device_id || app_id from user_log tmp2 having tmp2.log_day < tmp1.log_day)) a left join user_log b on a.log_day=(b.log_day - 1) and a.user_day0=b.(device_id || app_id) left join user_log c on a.log_day=(c.log_day - 3) and a.user_day0=c.(device_id || app_id) ) group by log_day;思路:如果是三天连续登录,首先把每一个用户单独判断,用到group by,并且在每个用户里进行日期的排序,row_number() over partition (order by ),或者使用datediff得到每天与最小一天的差形成新的一列。
join三个相同的表,我们查询的是第一个表,但是第一个表的日期的排序号码,可能在三天内的第一位,或者第二位,或者第三位,然后有 (s1.dayi = s2.dayi - 1 and s2.dayi = s3.dayi - 1) or (s2.dayi = s1.dayi - 1 and s1.dayi = s3.dayi - 1) or (s2.dayi = s3.dayi - 1 and s3.dayi = s1.dayi - 1)
交易表结构为user_id,order_id,pay_time,order_amount 写sql查询过去一个月付款用户量(提示 用户量需去重)最高的3天分别是哪几天 写sql查询做昨天每个用户最后付款的订单ID及金额
1)select count(distinct user_id) as c from table group by month(pay_time) order by c desc limit 3 2)select order_id, order_amount from ((select user_id, max(pay_time) as mt from table group by user_id where DATEDIFF(pay_time, NOW()) = -1 as t1) left join table as t2 where t1.user_id = t2.user_id and t1.mt == t2.pay_time) ———————————————— 版权声明:本文为博主「稻蛙」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u013382288/article/details/80450360
表结构为user_id,reg_time,age, 写一句sql按user_id随机抽样2000个用户 写一句sql取出按各年龄段(每10岁一个分段,如(0,10))分别抽样1%的用户 1)随机抽样2000个用户 select * from table order by rand() limit 2000
2)取出各年龄段抽样1%的用户 set @target = 0 set @count_user = 0 select @target:=@target+10 as age_right, * from table as t1 where t1.age >=@target-10 and t1.age < (@target) and t1.id in (select floor(count(*)*0.1) from table as t2 where t1.age >=@target-10 and t1.age < (@target) order by rand() limit ??)
用户登录日志表为user_id,log_id,session_id,plat,visit_date 用sql查询近30天每天平均登录用户数量 用sql查询出近30天连续访问7天以上的用户数量
1)近三十天每天平均登录用户数量
select visit_date, count(distinct user_id)
group by visit_date
2)近30天连续访问7天以上的用户数量
select t1.date
from table t1, table t2, …, table t7
on t1.visit_date = (t2.visit_date+1) and t2.visit_date = (t3.visit_date+1)
and … and t6.visit_date = (t7.visit_date+1)
1)近7天每天到访的新用户数
select day(visit_date), count(distinct user_id)
from table
where user_id not in
(select user_id from table
where day(visit_date) < date_sub(visit_date, interval 7day))
2)每个渠道7天前用户的3日留存和7日留存
三日留存 先计算每个平台7日前的新用户数量
select t1.plat, t1.c/t2.c as retention_3
(select plat, count(distinct user_id)
from table
group by plat, user_id
having day(min(visit_date)) = date_sub(now(), interval 7 day)) as t1
left join
(select plat, count(distinct user_id) as c
from table
group by user_id having count(user_id) > 0
having day(min(visit_date)) = date_sub(now(), interval 7 day)
and day(max(visit_date)) > date_sub(now(), interval 7 day)
and day(max(visit_date)) <= date_sub(now(), interval 4day)) as t2
on t1.plat = t2.plat