SQL学习笔记

https://blog.csdn.net/moguxiansheng1106/article/details/44258499

  1. Having与where的区别:https://baijiahao.baidu.com/s?id=1600513158500665764&wfr=spider&for=pc
  2. LEFT JOIN 关键字从左表(Websites)返回所有的行,即使右表(access_log)中没有匹配。
  3. 好评率是会员对平台评价的重要指标。现在需要统计2018年1月1日到2018年1月31日,用户’小明’提交的母婴类目"花王"品牌的好评率(好评率=“好评”评价量/总评价量):
    用户评价详情表:a
    字段:id(评价id,主键),create_time(评价创建时间,格式’2017-01-01’), user_name(用户名称),goods_id(商品id,外键) ,
    sub_time(评价提交时间,格式’2017-01-01 23:10:32’),sat_name(好评率类型,包含:“好评”、“中评”、“差评”)
    商品详情表:
    b 字段:good_id(商品id,主键),bu_name(商品类目), brand_name(品牌名称)
SELECT SUM(CASE

           WHEN sat_time = '好评' THEN 1

           ELSE 0

           END)/COUNT(sat_time) AS "好评率"

FROM a JOIN b ON a.good_id = b.good_id

WHERE user_name = '小明' AND sub_time BETWEEN ('2017-1-1') AND ('2017-1-31') AND b.bu_name = '母婴' AND b.brand_name ='花王'
  1. 考拉运营"小明"负责多个品牌的销售业绩,请完成:
    (1)请统计小明负责的各个品牌,在2017年销售最高的3天,及对应的销售额。
    销售表 a:
    字段:logday(日期,主键组),SKU_ID(商品SKU,主键组),sale_amt(销售额)
    商品基础信息表 b:
    字段:SKU_ID(商品SKU,主键),bu_name(商品类目),brand_name(品牌名称),user_name(运营负责人名称)
    (2)请统计小明负责的各个品牌,在2017年连续3天增长超过50%的日期,及对应的销售额。

(1)

select * from
(select b.brand_name, a.logday,row_number() OVER (PARTITION BY b.brand_name ORDER BY a.sale_amt desc) as num
from a join b on a.sku_id = b.sku_id
where year(a.logday)='2017' and b.user_name = '小明')c
where c.num <= 5
group by b.brand_name

(2)两表合并c->按品牌和时间分组,计算对应的销售额->前一天表和当天表按品牌合并->计算每个品牌在每一天的增长率->(未实现)
https://bbs.csdn.net/topics/392421965?page=1

create table a(
SKU_ID INT NOT NULL,
logday datetime NOT NULL,
sale_amt INT NOT NULL);
insert into a values (1,'2019-06-01',100);
insert into a values (2,'2019-06-01',200);
insert into a values (1,'2019-06-01',100);
insert into a values (4,'2019-06-01',300);
insert into a values (1,'2019-06-02',200);
insert into a values (2,'2019-06-02',150);
insert into a values (3,'2019-06-02',200);
insert into a values (4,'2019-06-02',100);
insert into a values (1,'2019-06-03',400);
insert into a values (3,'2019-06-03',80);
insert into a values (4,'2019-06-03',190);
insert into a values (4,'2019-06-04',390);
insert into a values (3,'2019-06-04',150);
insert into a values (1,'2019-06-05',150);
insert into a values (2,'2019-06-05',300);
insert into a values (3,'2019-06-05',200);
insert into a values (4,'2019-06-05',180);
insert into a values (2,'2019-06-05',300);
insert into a values (2,'2019-06-06',250);
insert into a values (2,'2019-06-06',350);

create table b(
SKU_ID INT NOT NULL,
brand_name varchar(12) NOT NULL,
user_name varchar(12) NOT NULL
);
insert into b values (1,'A','xm');
insert into b values (2,'A','xm');
insert into b values (3,'B','xm');
insert into b values (4,'B','xm');
with cte_1
as
(
select A.logday,B.brand_name, sum(A.sale_amt)as sum_amt
 from  A
 join  B on A.SKU_ID=B.SKU_ID
 where user_name='xm' 
 group by A.logday,B.brand_name),
cte_2
as
 (select logday, brand_name
 from cte_1 
)
select * from cte_2

在这里插入图片描述

  1. with as用法
    WITH AS短语,也叫做子查询部分(subquery factoring),如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。将WITH AS短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。
    with cr as( select CountryRegionCode from person);
    select * from cr;
    https://www.cnblogs.com/firstdream/p/7356481.html
    表有三个字段:id、node_name、parent_id。这个表中保存了一个树型结构,分三层:省、市、区。其中id表示当前省、市或区的id号、node_name表示名称、parent_id表示节点的父节点的id。现在有一个需求,要查询出某个省下面的所有市和区(查询结果包含省)
    SQL SERVER
create table t_tree
(
id int not null
,node_name varchar(50) not null
,parent_id int not null
,[description] varchar(255) null
)

insert into t_tree
(
id, node_name, parent_id
)

values
(1,'A',0),
(2 ,'B' ,1),
(3 ,'C' ,1),
(4 ,'D' ,2),
(5 ,'E' ,2),
(6 ,'F' ,2),
(7 ,'G' ,8)
with
district as
(
select * from t_tree where node_name=  'A'
union all
select a.* from t_tree a, district b
where a.parent_id = b.id
)
select * from district

https://www.w3school.com.cn/sql/sql_union.asp
在这里插入图片描述
6. INNER JOIN
INNER JOIN 与 JOIN 是相同的。INNER JOIN 关键字在表中存在至少一个匹配时返回行。
7. LEFT OUTER JOIN
left join 是 left outer join 的简写,两者含义一样的。一个LEFT OUTER JOIN包含“左”表中的所有记录,即使它与在此连接中指定的“右”表并不存在任何匹配。
8. PRIMARY KEY 约束
PRIMARY KEY 约束唯一标识数据库表中的每条记录。
主键必须包含唯一的值。
主键列不能包含 NULL 值。
每个表都应该有一个主键,并且每个表只能有一个主键。在表中,此主键可以包含单个或多个列(字段)。
9. 创建sql表
MYSQL5.6

-- borrowed from https://stackoverflow.com/q/7745609/808921
CREATE TABLE IF NOT EXISTS `docs` (
  `id` int(6) unsigned NOT NULL,
  `rev` int(3) unsigned NOT NULL,
  `content` varchar(200) NOT NULL,
  PRIMARY KEY (`id`,`rev`)
) DEFAULT CHARSET=utf8;
INSERT INTO `docs` (`id`, `rev`, `content`) VALUES
  ('1', '1', 'The earth is flat'),
  ('2', '1', 'One hundred angels can dance on the head of a pin'),
  ('1', '2', 'The earth is flat and rests on a bull\'s horn'),
  ('1', '3', 'The earth is like a ball.');
  1. sql server中的real数据类型
    float 和 real 数据类型被称为近似数据类型。近似数值数据类型并不存储为许多数字指定的精确值,它们只储存这些值的最近似值。float 和 real 的使用遵循有关近似数值数据类型的 IEEE 754 规范。IEEE 754 规范提供四种舍入模式:舍入到最近、向上舍入、向下舍入以及舍入到零。Microsoft SQL Server 2005 使用向上舍入。
    decimal(numeric ) 用于精确存储数值(整型)
    money 用于精确存储数值(浮点型)
    float 和 real 不能精确存储数值

  2. 利用SQL创建表时的 NOT NULL 约束:

CREATE TABLE test 
( 
age int(10), 
sex varchar(20), 
name varchar(20) NOT NULL 
)

NOT NULL 约束强制列不接受 NULL 值。
约束,就是限制某些东西不能干什么,或者说不能是什么样子。

  1. ord1表 user_id,ord_id,ord_amt,create_time,act_user
    act1表 act_id,user_id,create_time
    第一问:每个活动类型所有用户的总订单额,订单数
    第二问:每个活动类型活动开始时间(第一个用户报名的时间)到今天,平均每天产生的订单数

    创建ord1表, act1表 (MY SQL/ MS SQL SERVER)
create table ord1(
user_id INT NOT NULL,
ord_id  INT NOT NULL,
ord_amt REAL NOT NULL,
create_time datetime NOT NULL
);
INSERT INTO ord1 VALUES(1,10,100,'2019-07-02 10:00:01');
INSERT INTO ord1 VALUES(1,11,120,'2019-07-01 11:00:01');
INSERT INTO ord1 VALUES(1,11,120,'2019-07-02 11:00:01');
INSERT INTO ord1 VALUES(1,12,150,'2019-07-03 10:00:01');
INSERT INTO ord1 VALUES(2,13,200,'2019-07-02 10:00:01');
INSERT INTO ord1 VALUES(2,14,300,'2019-07-05 11:00:01');
INSERT INTO ord1 VALUES(3,15,100,'2019-07-02 10:00:01');
INSERT INTO ord1 VALUES(3,16,300,'2019-07-03 10:00:01');
INSERT INTO ord1 VALUES(4,17,200,'2019-07-02 10:00:01');
INSERT INTO ord1 VALUES(5,18,100,'2019-07-02 10:00:01');

create table act1(
act_id VARCHAR(15) NOT NULL,
user_id  INT NOT NULL,
create_time datetime NOT NULL
);
INSERT INTO act1 VALUES('A',1,'2019-07-02 10:00:01');
INSERT INTO act1 VALUES('A',2,'2019-07-02 11:00:01');
INSERT INTO act1 VALUES('A',3,'2019-07-02 10:00:01');
INSERT INTO act1 VALUES('B',4,'2019-07-02 10:00:01');
INSERT INTO act1 VALUES('B',5,'2019-07-02 10:00:01');
INSERT INTO act1 VALUES('C',6,'2019-07-02 10:00:01');

统计每个活动类型所有用户的总订单额,订单数

select 
	b.act_id
    ,count(ord_id)
    ,sum(ord_amt)
from ord1 a
join act1 b
on a.user_id = b.user_id
where a.create_time >= b.create_time
group by b.act_id;

每个活动类型活动开始时间(第一个用户报名的时间)到今天,平均每天产生的订单数

select 
	b.act_id
    ,sum(ord_amt)/DATEDIFF(day, min(a.create_time),'2019-7-28')  as avg
from ord1 a
left join act1 b
on a.user_id = b.user_id
where a.create_time >= b.create_time
group by b.act_id;
  1. log表(userid,opr_type,log_time)
    第一问:每天的访客数量
    第二问:每天执行opr_type=A到B,先A后B,而且必须紧紧挨着的用户数

    创建数据表
create table logtable(
user_id INT NOT NULL,
opr_type VARCHAR(15) NOT NULL,
log_time datetime NOT NULL);
insert into logtable values (1,'A','2019-06-01 10:10:01');
insert into logtable values (1,'B','2019-06-01 10:11:01');
insert into logtable values (1,'C','2019-06-01 10:12:01');
insert into logtable values (9,'A','2019-06-01 10:13:01');
insert into logtable values (9,'B','2019-06-01 10:14:01');
insert into logtable values (2,'A','2019-06-01 10:10:02');
insert into logtable values (2,'C','2019-06-01 10:11:01');
insert into logtable values (2,'B','2019-06-01 10:12:01');
insert into logtable values (3,'A','2019-06-02 10:10:01');
insert into logtable values (3,'B','2019-06-02 10:11:01');
insert into logtable values (4,'A','2019-06-03 10:10:01');
insert into logtable values (4,'C','2019-06-03 10:11:01');
insert into logtable values (4,'B','2019-06-03 10:12:01');

每天的访客数量

select date_format(log_time,'%y-%m-%d')
       ,count(distinct user_id)
from logtable 
group by date_format(log_time,'%y-%m-%d');

每天执行opr_type=A到B,先A后B,而且必须紧紧挨着的用户数
思路:增加新标签usertime(同user_id下大于当前log_id的注册时间的最小值), 并将其加入原数据表中;再通过特定标签进行右连接以保证A到B,先A后B,而且必须紧紧挨着的。最后通过注册时间进行分组,利用count()计算符合条件的用户数。

select date_format(t1.log_time,'%y-%m-%d')
	   ,count(distinct t1.user_id)
from (
select *,(select min(log_time) from logtable l2 where l2.user_id = l1.user_id and l2.log_time > l1.log_time) as usetime
from logtable as l1
) as t1
right join logtable as t2
on  t2.user_id=t1.user_id
where t2.opr_type = 'B'
and t1.opr_type = 'A'
and t2.log_time = t1.usetime
group by date_format
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值