上条记录和下一条记录
在展示博客文章时,在文章底部需要展示上一篇文章和下一篇文章,文章的排序当然是按照时间排序的。
选定下一条时可以用limit 1来实现,选取上一条时可以倒序limit 1实现
(SELECT * FROM article WHERE create_time<now_article_time ORDER BY create_time DESC LIMIT 1)
UNION
(SELECT * FROM article WHERE create_time>now_article_time ORDER BY create_time ASC LIMIT 1)
显示行号
Select a.*,(@rowNum:=@rowNum+1) as rowNo
From a,(Select (@rowNum :=3) ) b
通过变量rowNum来表示行号,在from子句中通过select语句给rowNum赋初值。这个过程涉及到SQL的执行顺序:即先执行from子句再执行select子句。
这种写法效率比较高,使用复合SQL语句的方式实现效率比较低(行号通过select语句来实现)。
MySQL打印学生成绩单
学生成绩单有语文、数学、英语三门成绩,如下所示:
语文 数学 英语
1 2 3
3 4 10
10 2 8
20 5 1
7 4 8
10 8 2
10 7 2
要求打印“rank(名次) sum(总分)”两列的成绩单(总分降序排列)。
SELECT 1 + (SELECT COUNT(1) FROM
stu AS y WHERE
y.chinese + y.math + y.english > x.chinese + x.math + x.english) AS rank,
(x.chinese + x.math + x.english) AS sum_score
FROM
stu AS x ORDER BY sum_score DESC;
这里用到了if函数,也可以通过SQL条件语句来实现:
case 表达式 when 取值1 then 答案1 when 取值2 then 答案2 else 答案3 end
这样写复杂度较高,下面这种方法比较简单。
SELECT rank, sum_score FROM
(SELECT
IF(@last_sum = x.chinese + x.math + x.english, @rank, @rank:=@rank + 1) AS rank,
(x.chinese + x.math + x.english) AS sum_score,
(SELECT @last_sum:=x.chinese + x.math + x.english) AS yy
FROM
stu AS x, (SELECT @last_sum:=- 1, @rank:=0) AS nothing
ORDER BY sum_score DESC) AS haha;
这里用到的技巧如下:
1、通过创建临时表、两重select来只选中某些列
2、在where子句中执行变量的初始化
3、在select子句中执行变量的更新
4、通过定义变量last_sum来记录上一条记录 的信息
5、通过比较上一条记录的总分跟当前记录的总分来决定是否让rank增加
SQL中的case语句
语法:
case [input_expression]
when when_expression then result_expression
[...n]
[else else_result_expression]
end
注:[]表示可选内容。
1、demo1:case后带表达式
select *,
case sgroup
when 1 then N'组1'
when 2 then N'组2'
when 3 then N'组3'
else N'未知' end groupname
from @stuinfo
2、demo2:case后不带表达式
select *,
case
when sgroup = 1 and gender = 'm' then N'第一组男生'
when sgroup = 1 and gender = 'f' then N'第一组女生'
when sgroup = 2 and gender = 'm' then N'第二组男生'
when sgroup = 2 and gender = 'f' then N'第二组女生'
when sgroup = 3 and gender = 'm' then N'第三组男生'
when sgroup = 3 and gender = 'f' then N'第三组女生'
else N'未知' end comment
from @stuinfo
3、demo3:在order by子句中使用case语句
select * from @stuinfo
order by
case when @orderby = 1 then id end desc,
case when @orderby = 2 then id end
这里要用多个case,因为desc需要放在end 后面,否则会有语法错误。
由此可以构造一道题:对一群学生成绩单进行排序,如果是男生按照数学成绩降序排列,如果是女生按照语文成绩降序排列,最终得到全体学生的成绩和名次。
这个问题不使用case语句也能实现,但是使用case 语句更简洁、效率更高。
一言以蔽之,case语句可以用在任何表达式中,有表达式的地方就可以有case语句。order by后面其实跟的也是表达式而不是列名。
SQL语句实现数据库表的数据迁移
国家标准分为强制性标准和推荐性标准,这两种标准的字段完全一致,当时建表时一时糊涂,分成了两个表。现在想合并force_standard、recommend_standard两张表为standard表,并加上字段is_force来表示该标准是否强制性标准。
当然可以通过一段代码,for循环实现,但那样麻烦,用SQL只需要一句话。
insert into standard(列名,列名,列名...is_force)
select 列名,列名,列名...,true from force_standard union
select 列名,列名,列名...,false from recommend_standard