目录

1.选取字段为【奇数或偶数问题】

2.【排序问题】

3.MySQL【新建表、修改表】

4.对于表批量【插入数据】,如果数据已经存在,则忽略

5.新建一个表,表中字段内容从另一个表导入

6.【索引】含义、原理、添加索引

强制索引:

7.MySQL【视图View】

8.MySQL【触发器】

9.修改表名

10.用【replace】替换个别数据

11.【DELETE】删除数据

12.创建外键约束

13.取两个表的交集【intersect】(SQL支持,MySQL不支持)

14.获取数据库中所有表名称

15.MySQL字符串截取总结【left, right, substring, substring_index】

16.连接字符串【concat(), group_concat()】

17. where后面不能跟分组函数avg, min, max, count, sum

18. mysql【分页查询】

19.mysql中的 【exists 与 in 】

20. 排列累加问题【sum() over()】

21. 选取表的奇数行、偶数行数据


1.选取字段为【奇数或偶数问题】

mysql判断奇数偶数,并思考效率https://blog.csdn.net/zhazhagu/article/details/80452473

mysql是可以用mod的,但牛客网的SQLite(应该是)不能用mod函数,只可以用 `字段名`%2 =0或1 进行判断

2.【排序问题】

MySQL实现排名函数RANK,DENSE_RANK和

ROW_NUMBER https://blog.csdn.net/u011726005/article/details/94592866

有三种排序方式,各有两种实现方法:1.变量法 2.函数法

对所有员工的当前(to_date='9999-01-01')薪水按照salary进行按照1-N的排名,相同salary并列且按照emp_no升序排列
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

emp_no salary rank
10005 94692 1
10009 94409 2
10010 94409 2
10001 88958 3
10007 88070 4
10004 74057 5
10002 72527 6
10003 43311 7
10006 43311 7
10011 25828 8

变量法:如果面试的话,这么写会加分的:

用了两个变量,变量使用时其前面需要加@,这里的:= 是赋值的意思,如果前面有Set关键字,则可以直接用=号来赋值,如果没有,则必须要使用:=来赋值,两个变量rank和pre,其中rank表示当前的排名,pre表示之前的工资,下面代码中的<>表示不等于,如果左右两边不相等,则返回true或1,若相等,则返回false或0。初始化rank为0,pre为-1,然后按降序排列工资,对于工资4来说,pre赋为4,和之前的pre值-1不同,所以rank要加1,那么工资4的rank就为1,下面一个分工资还是4,那么pre赋值为4和之前的4相同,所以rank要加0,所以这个工资4的rank也是1,以此类推就可以计算出所有工资的rank了

---牛客网别人的答案
SELECT emp_no,salary,(@`rank`:= @`rank`+ (@`pre`!= (@`pre`:= salary))) `Rank`
FROM salaries, (SELECT @`rank`:= 0, @`pre`:= -1) INIT
WHERE to_date = '9999-01-01'
group by emp_no
order by salary desc---或者用CASE WHEN (mysql里要给变量加上反引号)
select emp_no, salary,
(casewhen @pres=salary then @`rank`when @pres:=salary then @`rank`:=@`rank`+1
end) `Rank`
from salaries, (select @`rank`:=0,@pres:=-1) init
where to_date = '9999-01-01'
order by salary desc---或者用窗口函数
select emp_no, salary, dense_rank() over(order by salary desc) as rank
from salaries
where to_date='9999-01-01'
order by salary desc,emp_no asc

3.MySQL【新建表、修改表】

MYSQL添加、更新、删除数据 https://blog.csdn.net/qq_36734216/article/details/78611439

alter table的适用场景(添加、删除列等)https://www.cnblogs.com/lwcode6/p/11326666.html

alter/update 和 delete/drop的区别 https://www.cnblogs.com/lamian/p/3972562.html

在MySQL里,default CURRENT_TIMESTAMP,但在SQLite里面用的是 datetime('now','localtime')

---MySQL中创建表CREATE TABLE `table1` (`id` int(11) NOT NULL,`createtime` timestamp NULL default CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;---SQLite中创建表create table actor(
`actor_id` smallint(5) not null,
`first_name` varchar(45) not null,
`last_name` varchar(45) not null,
`last_update` timestamp not null default(datetime('now','localtime')),
primary key (`actor_id`))

alter table用法:

-- 对整型类型的字段设置默认值(可以这么设置)
alter table 表名 alter column `字段名` set default 6;-- 对时间类型的字段设置默认值(少了datetime/timestamp关键字,会无效)
alter table 表名 MODIFY column `字段名` datetime/timestamp  default CURRENT_TIMESTAMP;-- 错误的设置默认时间值语句
alter table 表名 alter column `字段名` set default CURRENT_TIMESTAMP;

4.对于表批量【插入数据】,如果数据已经存在,则忽略

如果不存在则插入,如果存在则忽略
INSERT IGNORE INTO tablename VALUES(...);如果不存在则插入,如果存在则替换
INSERT REPLACE INTO tablename VALUES(...);这里指的存在表示的是unique属性的列值存在的情况下,unique表示键值唯一

insert into:插入数据,如果主键重复,则报错
insert repalce:插入替换数据,如果存在主键或unique数据则替换数据
insert ignore:如果存在主键或unique数据,则忽略。

如果是在SQLite中,insert后面要加or,insert or replace, insert or ignore.

5.新建一个表,表中字段内容从另一个表导入

---mysql写法create table actor_name
select `first_name`, `last_name` from actor---SQLite写法(多了一个AS)create table actor_name as
select `first_name`, `last_name` from actor

6.【索引】含义、原理、添加索引

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。

MySQL索引原理以及查询优化 https://www.cnblogs.com/bypp/p/7755307.html

MySQL索引语法 https://www.runoob.com/mysql/mysql-index.html

1.普通索引#创建索引
CREATE INDEX indexName ON mytable(`username`(length)); #修改表结构(添加索引)
ALTER table tableName ADD INDEX indexName(`columnName`);#创建表的时候直接指定
CREATE TABLE mytable(  `ID` INT NOT NULL,    `username` VARCHAR(16) NOT NULL,   INDEX [indexName] (`username`(length))
);#删除索引
DROP INDEX [indexName] ON mytable;2.唯一索引#创建索引
CREATE UNIQUE INDEX indexName ON mytable(`username`(length)) #修改表结构(添加索引)
ALTER table mytable ADD UNIQUE [indexName] (`username`(length));#创建表的时候直接指定
CREATE TABLE mytable(  `ID` INT NOT NULL,   `username` VARCHAR(16) NOT NULL,  UNIQUE [indexName] (`username`(length))
);  #删除索引
DROP INDEX [indexName] ON mytable;3.使用ALTER 命令添加和删除索引有四种方式来添加数据表的索引:ALTER TABLE tbl_name ADD PRIMARY KEY (`column_list`): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。ALTER TABLE tbl_name ADD UNIQUE index_name (`column_list`): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。ALTER TABLE tbl_name ADD INDEX index_name (`column_list`): 添加普通索引,索引值可出现多次。ALTER TABLE tbl_name ADD FULLTEXT index_name (`column_list`):该语句指定了索引为 FULLTEXT ,用于全文索引。以下实例为在表中添加索引。
mysql> ALTER TABLE testalter_tbl ADD INDEX (`c`);你还可以在 ALTER 命令中使用 DROP 子句来删除索引。尝试以下实例删除索引:
mysql> ALTER TABLE testalter_tbl DROP INDEX `c`;4.使用 ALTER 命令添加和删除主键主键只能作用于一个列上,添加主键索引时,你需要确保该主键默认不为空(NOT NULL)。实例如下:mysql> ALTER TABLE testalter_tbl MODIFY `i` INT NOT NULL;
mysql> ALTER TABLE testalter_tbl ADD PRIMARY KEY (`i`);
你也可以使用 ALTER 命令删除主键:mysql> ALTER TABLE testalter_tbl DROP PRIMARY KEY;
删除主键时只需指定PRIMARY KEY,但在删除索引时,你必须知道索引名。5.显示索引信息你可以使用 SHOW INDEX 命令来列出表中的相关的索引信息。可以通过添加 \G 来格式化输出信息。尝试以下实例:
mysql> SHOW INDEX FROM table_name; \G

强制索引:

SQLite中,使用 INDEXED BY 语句进行强制索引查询,可参考:

http://www.runoob.com/sqlite/sqlite-indexed-by.html

SELECT * FROM salaries INDEXED BY idx_emp_no WHERE emp_no = 10005

http://www.jb51.net/article/49807.htm

MySQL中,使用 FORCE INDEX 语句进行强制索引查询,可参考:

SELECT * FROM salaries FORCE INDEX idx_emp_no WHERE emp_no = 10005

7.MySQL【视图View】

MySQL 视图(View)是一种虚拟存在的表,同真实表一样,视图也由列和行构成,但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的表,并且还是在使用视图时动态生成的。

数据库中只存放了视图的定义,并没有存放视图中的数据,这些数据都存放在定义视图查询所引用的真实表中。使用视图查询数据时,数据库会从真实表中取出对应的数据。因此,视图中的数据是依赖于真实表中的数据的。一旦真实表中的数据发生改变,显示在视图中的数据也会发生改变。

视图可以从原有的表上选取对用户有用的信息,那些对用户没用,或者用户没有权限了解的信息,都可以直接屏蔽掉,作用类似于筛选。这样做既使应用简单化,也保证了系统的安全。

视图(View)是一种虚表,允许用户实现以下几点:

  • 用户或用户组查找结构数据的方式更自然或直观。

  • 限制数据访问,用户只能看到有限的数据,而不是完整的表。

  • 汇总各种表中的数据,用于生成报告。

SQLite 视图是只读的,因此可能无法在视图上执行 DELETE、INSERT 或 UPDATE 语句。但是可以在视图上创建一个触发器,当尝试 DELETE、INSERT 或 UPDATE 视图时触发,需要做的动作在触发器内容中定义。

1.创建视图CREATE VIEW <视图名> AS <SELECT语句>在 tb_students_info 表上创建一个名为 v_students_info 的视图,输入的 SQL 语句和执行结果如下所示CREATE VIEW v_students_info(s_id,s_name,d_id,s_age,s_sex,s_height,s_date)
AS SELECT `id`,`name`,`dept_id`,`age`,`sex`,`height`,`login_date`
FROM tb_students_info;2.查看视图select * from tb_students_info;  ---查看视图具体数据show create view tb_students_info ---查看视图3.删除视图
drop view tb_students_info

8.MySQL【触发器】

触发器就是当达成一定条件时,执行特定语句,可以用于监测事件的发生。

MySQL触发器更新和插入操作 https://blog.csdn.net/Eastmount/article/details/52344036

9.修改表名

题目是sqlite3,必须要加to

alter table titles_test rename to titles_2017

如果是mysql,不用加to

alter table titles_test rename titles_2017

10.用【replace】替换个别数据

将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现。
CREATE TABLE IF NOT EXISTS titles_test (
id int(11) not null primary key,
emp_no int(11) NOT NULL,
title varchar(50) NOT NULL,
from_date date NOT NULL,
to_date date DEFAULT NULL);

insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'),
('2', '10002', 'Staff', '1996-08-03', '9999-01-01'),
('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'),
('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'),
('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'),
('6', '10002', 'Staff', '1996-08-03', '9999-01-01'),
('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01');

解法:

方法一:全字段更新替换。由于 REPLACE 的新记录中 id=5,与表中的主键 id=5 冲突,故会替换掉表中 id=5 的记录,否则会插入一条新记录(例如新插入的记录 id = 10)。并且要将所有字段的值写出,否则将置为空。可参考:

http://blog.csdn.net/zhangjg_blog/article/details/23267761

REPLACE INTO titles_test VALUES (5, 10005, 'Senior Engineer', '1986-06-26', '9999-01-01')

http://www.cnblogs.com/huangtailang/p/5cfbd242cae2bcc929c81c266d0c875b.html

方法二:运用REPLACE(X,Y,Z)函数。其中X是要处理的字符串,Y是X中将要被替换的字符串,Z是用来替换Y的字符串,最终返回替换后的字符串。以下语句用 UPDATE和REPLACE 配合完成,用REPLACE函数替换后的新值复制给 id=5 的 emp_no。REPLACE的参数为整型时也可通过。可参考:

http://sqlite.org/lang_corefunc.html#replace

UPDATE titles_test SET emp_no = REPLACE(emp_no,10001,10005) WHERE id = 5

/** 另外可以利用OJ系统的漏洞,不用 REPLACE 实现  **/

UPDATE titles_test SET emp_no = 10005 WHERE id = 5

11.【DELETE】删除数据

删除emp_no重复的记录,只保留最小的id对应的记录。
CREATE TABLE IF NOT EXISTS titles_test (
id int(11) not null primary key,
emp_no int(11) NOT NULL,
title varchar(50) NOT NULL,
from_date date NOT NULL,
to_date date DEFAULT NULL);

MYSQL:

MySQL的UPDATE或DELETE中子查询不能为同一张表可将查询结果再次SELECT。

详见https://www.cnblogs.com/cuisi/p/7372333.html

DELETE FROM titles_test
WHERE id NOT IN (SELECT * FROM(SELECT MIN(id) FROM titles_test GROUP BY emp_no
) AS a);

这在OJ中也可执行。

另外,在MySQL中还有一个坑,需要给子查询添加别名,不然会抛出错误:ERROR 1248 (42000): Every derived table must have its own alias,详见:https://blog.csdn.net/cao478208248/article/details/28122113

SQLite可以直接:

DELETE FROM titles_test WHERE id NOT IN
(SELECT MIN(id) FROM titles_test GROUP BY emp_no)

12.创建外键约束

SQLite中不能使用alter table...add foreign key...references...,对已经创建的表只能drop。。。(毫无意义,表都没有了)

drop table audit;
CREATE TABLE audit
(EMP_no INT NOT NULL,
create_date datetime NOT NULL,
FOREIGN KEY(EMP_no) REFERENCES employees_test(ID));

MySQL下,可以直接使用如下语句 修改:

alter table audit
add foreign key(emp_no) references employees_test(id)

13.取两个表的交集【intersect】(SQL支持,MySQL不支持)

存在如下的视图:
create view emp_v as select * from employees where emp_no >10005;
如何获取emp_v和employees有相同的数据?
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

select * from emp_v intersect select * from employees


intersect:求交集

或者普通方法,MYSQL就可以用in来实现两个数据集的交集:

select *
from employees e
where e.emp_no in(
select emp_no
from emp_v)

14.获取数据库中所有表名称

针对库中的所有表生成select count(*)对应的SQL语句

输出格式:

cnts
select count(*) from employees;
select count(*) from departments;
select count(*) from dept_emp;
select count(*) from dept_manager;
select count(*) from salaries;
select count(*) from titles;
select count(*) from emp_bonus;

sqlite写法(牛客网通过):

1

2

3

select "select count(*) from "||name||";" as cnts

    from sqlite_master 

    where type='table';

mysql写法(牛客网不通过,但是我在自己的mysql上运行通过):

1

2

select concat("select count(*) from "," ",table_name,";") as cnts

from (select table_name from information_schema.tables where table.schema = '数据库名') as new;

15.MySQL字符串截取总结【left, right, substring, substring_index】

参考文章 https://www.cnblogs.com/heyonggang/p/8117754.html

16.连接字符串【concat(), group_concat()】

参考文章 浅析MySQL中concat以及group_concat的使用

一、concat()函数

1、功能:将多个字符串连接成一个字符串。

2、语法:concat(str1, str2,...)

返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。

二、concat_ws()函数

1、功能:和concat()一样,将多个字符串连接成一个字符串,但是可以一次性指定分隔符~(concat_ws就是concat with separator)

2、语法:concat_ws(separator, str1, str2, ...)

说明:第一个参数指定分隔符。需要注意的是分隔符不能为null,如果为null,则返回结果为null。

三、group_concat()函数

前言:在有group by的查询语句中,select指定的字段要么就包含在group by语句的后面,作为分组的依据,要么就包含在聚合函数中。(有关group by的知识请戳:浅析SQL中Group By的使用)。

1、功能:将group by产生的同一个分组中的值连接起来,返回一个字符串结果。

2、语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc  ] [separator '分隔符'] )

说明:通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用order by子句;separator是一个字符串值,缺省为一个逗号。

转载  https://blog.csdn.net/Mary19920410/article/details/76545053


按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果employees
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
输出格式:

dept_no employees
d001 10001,10002
d002 10006
d003 10005
d004 10003,10004
d005 10007,10008,10010
d006 10009,10010

解法:

本题要用到SQLite的聚合函数group_concat(X,Y),其中X是要连接的字段,Y是连接时用的符号,可省略,默认为逗号。此函数必须与 GROUP BY 配合使用。此题以 dept_no 作为分组,将每个分组中不同的emp_no用逗号连接起来(即可省略Y)。可参考:

http://www.sqlite.org/lang_aggfunc.html#groupconcat   http://blog.csdn.net/langzxz/article/details/16807859

1

2

SELECT dept_no, group_concat(emp_no) AS employees

FROM dept_emp GROUP BY dept_no

MYSQL的写法:(多一个separator)

select dept_no,group_concat(emp_no SEPARATOR ',') from dept_emp group by dept_no;

17. where后面不能跟分组函数avg, min, max, count, sum

查找排除当前最大、最小salary之后的员工的平均工资avg_salary。
CREATE TABLE `salaries` ( `emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
输出格式:

avg_salary
69462.5555555556

错误写法:

select avg(salary) as avg_salary

from salaries
where salary>min(salary) and salary<max(salary)

and to_date='9999-01-01'

错误原因:where 后面不能跟分组函数,因为执行顺序是先执行where 之后才执行分组,还没有分组的时候是无法运行min,max,avg,sum,count这类函数的!

参考文章 为什么sql语句中where后面不能直接跟分组函数?--详解https://blog.csdn.net/liangjiabao5555/article/details/105474876

解决方法:将where后面的分组函数改成子查询!

正确解法:

select avg(salary) as avg_salary
from salaries
where salary>(select min(salary) from salaries) and salary<(SELECT max(salary) from salaries)
and to_date='9999-01-01'

18. mysql【分页查询】

分页查询employees表,每5行一页,返回第2页的数据
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

参考文章 MySQL实现分页查询

语法:select * from table limit (pageNo-1)*pageSize,pageSize;

在数据量较小的时候简单的使用 limit 进行数据分页在性能上面不会有明显的缓慢,但是数据量达到了 万级到百万级 sql语句的性能将会影响数据的返回。这时需要利用主键或者唯一索引进行数据分页;

假设主键或者唯一索引为 good_id
收到客户端{pageNo:5,pagesize:10}
select * from table where good_id > (pageNo-1)*pageSize limit pageSize;
–返回good_id为40到50之间的数据

当需要返回的信息为顺序或者倒序时,对上面的语句基于数据再排序。order by ASC/DESC 顺序或倒序 默认为顺序

select * from table where good_id > (pageNo-1)*pageSize order by good_id limit pageSize;
–返回good_id为40到50之间的数据,数据依据good_id顺序排列

19.mysql中的 【exists 、not exists 与 in 】

使用含有关键字exists查找未分配具体部门的员工的所有信息。
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

思路:在 employees 中挑选出令(SELECT emp_no FROM dept_emp WHERE emp_no = employees.emp_no)不成立的记录

SELECT * FROM employees WHERE NOT EXISTS
(SELECT emp_no FROM dept_emp WHERE emp_no = employees.emp_no)

 错误写法:

select * from employees
where  exists( select emp_no from dept_emp where dept_emp.emp_no != employees.emp_no)

那么,Exists都会从外表employees里面逐条比对,如,第一条的emp_no = '10001',那么Exists判断:

select emp_no from dept_emp where dept_emp.emp_no !='10001'

因为一定存在dept_emp.emp_no不等于10001的记录。那么上面的查询语句其实也就等效于查询select * from employees

参考文章 浅析MySQL中exists与in的使用 (写的非常好)

另一篇文章教我怎么理解exists和not exists,强烈推介!!exists与not exists的原理讲解

exists筛选结果集为true的数据项,而not exists相反,返回结果集为false的数据项

如果查询的两个表大小相当,那么用in和exists差别不大

如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:

例如:表A(小表),表B(大表)

1:

select * from A where cc in (select cc from B) 效率低,用到了A表上cc列的索引;

select * from A where exists(select cc from B where cc=A.cc) 效率高,用到了B表上cc列的索引。

相反的

2:

select * from B where cc in (select cc from A) 效率高,用到了B表上cc列的索引;

select * from B where exists(select cc from A where cc=B.cc) 效率低,用到了A表上cc列的索引。

not in 和not exists如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快

in 与 =的区别

select name from student where name in ('zhang','wang','li','zhao');

select name from student where name='zhang' or name='li' or name='wang' or name='zhao'

的结果是相同的。

20. 排列累加问题【sum() over()】

按照salary的累计和running_total,其中running_total为前两个员工的salary累计和,其他以此类推。 具体结果如下Demo展示。。
CREATE TABLE `salaries` ( `emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
输出格式:

emp_no salary running_total
10001 88958 88958
10002 72527 161485
10003 43311 204796
10004 74057 278853
10005 94692 373545
10006 43311 416856
10007 88070 504926
10009 95409 600335
10010 94409 694744
10011 25828 720572

SQLite不能用窗口函数over( ),有一种通用的模板(mysql也可以用):

复用salaries表

select a.emp_no, a.salary, sum(b.salary) as running_total
from salaries a, salaries b
where b.emp_no<=a.emp_no and a.to_date='9999-01-01' and b.to_date='9999-01-01'
group by a.emp_no, a.salary
ORDER BY a.emp_no

MySQL里有两种解法:临时变量法和窗口函数

(1)临时变量法

select emp_no, salary, (@`pres`:=@`pres`+salary) running_total
from salaries, (@`pres`:=0) init
where to_date='9999-01-01'
order by emp_no

(2)窗口函数 sum() over()

select emp_no, salary, sum(salary) over(order by emp_no asc) as running_total
from salaries
where to_date='9999-01-01'

21. 选取表的奇数行、偶数行数据

对于employees表中,给出奇数行的first_name
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
输出格式:

first_name
Georgi
Chirstian
Anneke
Tzvetan
Saniya
Mary

两种方法:普通法和临时变量法

(1)普通法(网友答案):(线下用mysql测试,近50w条数据,查询速度非常慢)

select c.first_name
from
(select a.first_name,(select count(*)from employees bwhere b.first_name<=a.first_name) rownum
from employees a) c
where c.rownum%2=1--中间不建临时表的写法
select first_name
from employees e1
where (select count(*) from employees e2 where e2.first_name<=e1.first_name)%2=1

思路:首先复用表,先建立新的一列,这一列包含每一行的行数,计算行号的方法 : 有多少个小于等于a.first_name的记录的个数就是a.first_name的行号。例如输入a表第1行进去,此时小于a.first_name的记录数为1;输入a表第二行进去,此时小于a.first_name的记录数共有2个,表示为第2行...下一步是挑选出rownum为奇数的行,即可。

select a.first_name,(select count(*)from employees bwhere b.first_name<=a.first_name) rownum
from employees a

(2)临时变量法(SQLite无法使用,线下测试通过,查询速度非常快)

select a.first_name
from
(select first_name, (@row:=@row+1) rownum
from employees,(select @row:=0) init) a
where a.rownum%2=1

牛客网SQL刷题问题汇总相关推荐

  1. 牛客网SQL刷题笔记(MySQL)

    牛客网SQL刷题笔记(MySQL) 此博客集合LeetCode.牛客网常见的题型及其解法,侵删 目录 牛客网SQL刷题笔记(MySQL) 类型1:查找排名第几的数据 SQL2 查找入职员工时间排名倒数 ...

  2. sql里查询一个组和组的用户数怎么查?_【牛客网SQL刷题】留存率怎么算?

    抽空刷了牛客网SQL实战72题,最后几道以牛客网为例的题目还挺有挑战性,在此记录 统计时间段新用户次日留存率 每日的次日留存率 每日的新用户数 每日新用户的次日留存 求新登录用户次日留存 表login ...

  3. 牛客网SQL刷题笔记总结

    非技术快速入门 1.基础查询 (1)基础查询 查询单列:查询所需的列名写在 SELECT 关键字之后,FROM 关键字指出从哪个表中查询数据. select device_id from user_p ...

  4. 牛客网SQL刷题四-电商场景(某东商城)

    SQL13 计算商城中2021年每月的GMV 数据 DROP TABLE IF EXISTS tb_order_overall; CREATE TABLE tb_order_overall (id I ...

  5. 牛客网SQL刷题二-某音短视频

    SQL1 各个视频的平均完播率 数据 DROP TABLE IF EXISTS tb_user_video_log, tb_video_info; CREATE TABLE tb_user_video ...

  6. 牛客网java刷题笔记2019-1-4

    牛客网java刷题笔记 2019-1-4 1.java中可以用类中构造器调用其他类构造器(这个和C++中构造函数很类似)用于初始化程序变量值, 构造器和方法的区别: 功能和作用的不同 构造器是为了创建 ...

  7. 牛客网Java刷题知识点之关键字static、static成员变量、static成员方法、static代码块和static内部类...

    不多说,直接上干货! 牛客网Java刷题知识点之关键字static static代表着什么 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个"伪全局"的概 ...

  8. 牛客网Java刷题知识点之构造函数可以调用一般函数,但是一般函数不可以直接调用构造函数...

    不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...

  9. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合...

    不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...

最新文章

  1. xml笔记整理_基础概括
  2. 用pytorch加载训练模型
  3. javascript之构造器
  4. Usage of git
  5. 数据自治开放模式下的隐私保护
  6. 遇到一个把.o文件strip后出现的奇怪问题
  7. [转载] pickle:让python对象序列化
  8. 设计模式六大原则-OCP
  9. sql中DistinctCount的用法
  10. 阿里巴巴代码规范 学习总结
  11. 路畅安卓最新固件升级_路畅导航系统固件升级大全下载 v1.51 官方版
  12. Morrios灵敏度分析法
  13. exception1:unicodeescape’ codec can’t decode bytes in position XXX: trun错误解决方案
  14. python反素数_可逆素数-随心随性无为而为-51CTO博客
  15. 区块链网络的价值是啥?
  16. 基于lora模块智能井盖解决方案
  17. 聚合API文档阅读帮助
  18. 离岸账户这么难开,还有什么更好地途径?
  19. UE4 场景展示Demo
  20. 电脑不能连接网络的解决办法

热门文章

  1. 风口上的低代码:诱人的故事,危险的豪赌
  2. 在商城项目开发中怎么保证促销商品不会超卖
  3. html check选中状态,html checkbox选中
  4. 产品3C认证证书暂停要怎么恢复,3C证书没有年审怎么办?
  5. 硬盘知识大全(含主板、BIOS)
  6. SQL Server 2008 (2008 R2) 清理日志方法
  7. ubuntu清理缓存
  8. 基金使用计划 数学建模 matlab,01B基金使用计划(数学建模).ppt
  9. 博客发在oschina
  10. Java面试题-进阶篇(2022.4最新汇总)