用于 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. select top
2. from table
3. join table_B on ...
4. join table_C on...
5. where
6. group by var1
7. having ...
8. order by ...
参考
执行顺序
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),倒数三个
相同点:
不同点:
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%
原因:
如何调优:
1)Hadoop原理:采用HDFS(Hadoop Distributed File System)分布式存储文件,MapReduce分解计算,其它先略
2)MapReduce原理:
a. map阶段:读取HDFS中的文件,解析成
的形式,并对 进行分区(默认一个区),将相同k的value放在一个集合中
b. reduce阶段:将map的输出copy到不同的reduce节点上,节点对map的输出进行合并、排序
————————————————
版权声明:本文为CSDN博主「稻蛙」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013382288/article/details/80450360
1)字符串:char、varchar、text
2)二进制串:binary、varbinary
3)布尔类型:boolean
4)数值类型:integer、smallint、bigint、decimal、numeric、float、real、double
5)时间类型:date、time、timestamp、interval
有两个表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);
(case var_0 when 1 then var_1 * 0.1
when 2 then var_1 * 0.2
else var_1 * 0.3 end) as var_3
下面的例子是,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);
————————————————
版权声明:本文为CSDN博主「稻蛙」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013382288/article/details/80450360
SET @row_number = 0;
SELECT (@row_number:=@row_number + 1) AS num FROM table;
字段及表说明:
表名: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)
————————————————
版权声明:本文为CSDN博主「稻蛙」的原创文章,遵循 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