MYSQL 双表联查 + 统计 + 排序

mysql 单表多次查询和多表联合查询,哪个效率高? - 知乎72被浏览22952分享邀请回答0添加评论分享收藏感谢收起502 条评论分享收藏感谢收起查看更多回答mysql查询2张表的数据,并按照统计字段数据的大小排序? - 知乎2被浏览349分享邀请回答0添加评论分享收藏感谢收起查看: 6545|回复: 12
Mysql 多表多列排序问题,效率很慢啊
论坛徽章:0
小弟现在在优化一个功能的查询语句
& &可是在查询优化的时候遇到了瓶颈,现在请各位大哥们帮忙了
& &表关系描述如下
& && && && && && & A 表为实际的记录表 大概60万条记录
& && && && && && & B 表为 A表和权限表的关系表 表结构为 权限id 和 A表id
& && && && && && & C 表为员工信息表
& && && && && && & A表中有一个字段为C表(员工表id)
& &查询语句描述(主要是Hibernate的HQL语句)
& && && && && && & select a.* from A as a inner join B as b inner join C as c
& && && && && && & where b.id=?
& && && && && && & order by&&a.创建日期 desc,a.创建时间 desc,c.员工姓名,c.工号
& &现在的查询语句 获取20条分页记录为1分钟,已经建立索引,时间主要消耗在 排序方面,请各位高人给出出主意,怎样优化一下查询
[ 本帖最后由 lt-2046 于
11:13 编辑 ]
论坛徽章:0
论坛徽章:52
select a.* from A as a inner join B as b inner join C as c
& && && && && && & where b.id=?
& && && && && && & order by&&a.创建日期 desc,a.创建时间 desc,c.员工姓名,c.工号
这种SQL是找抽型......
论坛徽章:52
假设表A(id,Cid,Bid,gmt_create....)
那只要这样写:
SELECT * FROM A WHERE Bid=? ORDER BY id DESC,Cid
论坛徽章:0
因为数据层用的是Hibernate的Hql,所以比较纠结
会产生这种查询语句主要是因为查询条件是动态的,还有很多条件没有贴出来,只拿最简单的语句说明问题
现在想通过视图来优化,可是发现在 排序 的时候同样没有使用到索引
视图的 ALGORITHM =&&MERGE
mysql的官方文档说 MERGE 类型可以使用索引
所以现在有点疑惑
论坛徽章:52
回复 #5 lt-2046 的帖子
那我收回那句话....并且说声 对不起!
Hibernate是实现了开发人员分工,以及加速开发等优势,但是也带来性能上的问题
所以这个东东需要权衡,以及规避其风险的地方...
论坛徽章:0
现在的方案
一&&。是把几张表提取成一张视图,可是生成的视图同样不支持索引(Mysql&&5.0 版本)
在 mysql 5.1&&文档中 视图部分说如果是 ALGORITHM =&&MERGE 这种类型的是可以使用索引的
还没来得及测试
二&&。是把C表(员工表)中的排序字段在A表中添加一遍,可是这样就造成了数据冗余,将来维护起来会很麻烦
希望有经验的朋友来给点意见
论坛徽章:52
回复 #7 lt-2046 的帖子
适当的冗余是有好处的,还有就是那个排序是否非要用到C表的字段
因为只用于排序的话,建议是撤了....或者考虑换其他方式可以实现同等效果
这个方案需要跟你的业务有关系
论坛徽章:4
我觉得面向对象要适量,过于追求面向对象表拆的太分散并不好,做好恰当的冗余更重要。
论坛徽章:395
不知道mysql支持几种连接算法,nest loop/ hash join/ merge join/
itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有    
 北京市公安局海淀分局网监中心备案编号:10 广播电视节目制作经营许可证:编号(京)字第1149号//多表查询:得到最新的数据后再执行多表查询SELECT *FROM `students` `st` RIGHT JOIN(
SELECT * FROM   (    SELECT * FROM goutong WHERE goutongs='asdf' ORDER BY time DESC  ) AS gtt GROUP BY gtt.name_id ORDER BY gtt.goutong_time DESC ) gt   ON `gt`.`name_id`=`st`.`id` LIMIT 10
//先按时间排序查询,然后分组(GROUP BY ) SELECT * FROM
    SELECT * FROM goutong WHERE goutongs='asdf' ORDER BY time DESC  ) AS gtt GROUP BY gtt.name_id ORDER BY gtt.time DESC
参考:http://blog.csdn.net/shellching/article/details/8292338
有数据表 comments
------------------------------------------------
| id | newsID | comment |
------------------------------------------------
| 1 &| & & & &1 & & &| & & & & aaa & &| & & 11 & & & |
------------------------------------------------
| 2 &| & & & &1 & & &| & & & & bbb & &| & & 12 & & & |
------------------------------------------------
| 3 &| & & & &2 & & &| & & & & ccc & & | & & 12 & & & |
------------------------------------------------
newsID是新闻ID,每条新闻有多条评论comment,theTime是发表评论的时间
现在想要查看每条新闻的最新一条评论:
select * from comments group by newsID 显然不行
select * from comments group by newsID order by theTime desc
是组外排序,也不行
下面有两种方法可以实现:
selet tt.id,tt.ment,tt.theTime from( &
select id,newsID,comment,theTime from comments order by theTime desc) as tt group by newsID&
select id,newsID,comment,theTime from comments as tt group by id,newsID,comment,theTime having
&theTime=(select max(theTime) from comments where newsID=tt.newsID)
补充: 通过最大时间 然后再联合查询出其它信息,实现避免分组排序的问题。(多个子查询实现功能)
'SELECT gt.time,
gt.name_id,
gt.goutong,gt.operator, st.id,st.Stu_name,st.Stu_sex,st.stu_gongsi,st.stu_waishangke,st.Stu_jjcourse,st.Stu_phone,st.Stu_beizhu FROM jingjie_students AS st RIGHT JOIN (SELECT A.* FROM jingjie_goutong A, (SELECT name_id,MAX(goutong_time) goutong_time FROM jingjie_goutong WHERE
operator = '小明' GROUP BY name_id) B WHERE A.name_id = B.name_id AND A.time = B.time
ORDER BY A.time DESC LIMIT 0,10) gt ON st.id = gt.name_id';
阅读(...) 评论()史安平是一个对编程,吉他,美食,中医,健身充满了喜爱的废材,但他没有放弃,依然孜孜不倦的行走在路上,探寻生命的意义 - 欢迎来到我的博客
当前位置:
[MYSQL基础]聚合函数_分组和多表连接查询
[MYSQL基础]聚合函数_分组和多表连接查询
字体大小: [
作用:去掉结果集中的重复记录
出现在查询语句字段列表中
当结果集中所有字段的值相同,才是重复记录
作用:给表或字段起别名
select age,name,brief j from psd_
作用:用来和null值进行比对
count(字段名)
获取结果集某字段下记录的总条数
获取分组后,每组中记录的条数
分组查询(count())
group by sex& --把男生放一组,女生放一组
例子:计算所有学生中男生,女生个有多少人
select count(sex) as num,sex from psd_student group by sex
练习:计算每一个班的总人数
select count(classid) num,classid from psd_stud
having 条件
作用:对分组的统计结果再进行筛选
例子:统计学生人数大于等于5的班级都有哪个?????
1、知道每个班多少人
select count(classid) as num,classid from psd_stud
2、根据班级人数,进行筛选
select count(classid) as num,classid from psd_student group by classid having num>=5;
group by 和having一般是成对出现
练习:统计哪个年龄的人数最多
1、每个年龄对应的人数
select count(age) as num,age from psd_
2、倒序排序
select count(age) as num,age from psd_student group by a
多表联查(多张有关系的表进行联查)
select tableA.字段,tableB.字段& from tableA inner join tableB on tableA.字段=tabelB.字段 where 子句 group by 子句 having 子句 order by 子句 limit子句
需求:查询小王他的班级名称
sid name sex age classid brief
1&& 小王& 男& 21& 1&&&&& null
2&& 小li& 男& 21& 1&&&&& null
3&& 小zhang& 男& 21& 2&&&&& null
4&& 小sun& 男& 21& 1&&&&& null
5&& 小sun& 男& 21& 3&&&&& null
classid cname
1&&&&&& psd1306
2&&&&&& psd1307
1&& 小王& 男& 21& 1&&&&& null&&&& 1&& psd1306
2&& 小li& 男& 21& 1&&&&& null&&&& 1&& psd1306
3&& 小zhang& 男& 21& 2&&&&& null& 2&& psd1307
4&& 小sun& 男& 21& 1&&&&& null&&& 1&& psd1306
5&& 小sun& 男& 21& 3&&&&& null&&& null null
两个表连接
select * from psd_student as s join psd_class c on s.classid=c.
查询小王他的班级名称
1、不用连接
查询小王的班级id
select classid from psd_student where name="小王"
查询班级id对应的班级名称
select cname from psd_class where classid=1
2、连接查询
ame from psd_student as s join psd_class c on s.classid=c.classid where s.name="小王";
左连接(以左边的表为主表去连接右边的表,如果右边的表中没有记录用null补齐)
ame from psd_student as s left join psd_class c on s.classid=c.classid
右连接(以右边的表为主表去连接左边的表,如果左边的表中没有记录用null补齐)
ame from psd_student as s right join psd_class c on s.classid=c.classid
练习:统计每个班的人数,在结果集中出现班级名称
select * from psd_student s join psd_class c on s.classid=c.classid
2、分组,求每组中人数
ame,count(s.classid) num from psd_student s join psd_class c on s.classid=c.classid group by s.classid having num>=3;
1、select 字段列表 from (查询语句) as 别名;
例子:查询班级id为1的班,男生年龄大于25的都有谁
select * from (select * from psd_student where classid=1 and sex="男") as s where s.age>25
2、select 字段列表 from 表名 where 字段名 in(查询语句)
例子:查询班级psd1306及psd1308的学生
select * from psd_student where classid in(select classid from psd_class where cname="psd1306" or cname="psd1308");
union(结果集的连接)
要求:结果集中字段的个数必须相同
select name,sex from psd_student union select tname,1 from psd_
union all(结果集的连接,重复值保留)
count(字段名)-----对结果集或组中记录条数求总条数
avg(字段名)----对每组中的某个字段求平均数
min(字段名)----找某个字段下的最小值
max(字段名)----找某个字段下的最大值
sum(字段名)
round(字段名)---对某个字段做四舍五入处理
ceil(字段名)---对字段的值向上取整
floor(字段名)----对字段的值向下取整
说明:一般和分组同时使用
1、在学生表中,找出男生年龄最大者,和女生年龄最大者。
select max(age),sex from psd_student where sex!="保密" group by sex
2、在学生表中,求出男生平均年龄,女生平均年龄。
select avg(age),sex from psd_student where sex!="保密"
select sum(age),sex from psd_student where sex!="保密"
replace(字段名,"search","replace")
作用:字符串替换
&& &查询语句的字段列表
&& &update语句的 字段名=值,在值位置出现
查询学生信息,简介中包含“李洪志”的,过滤掉。
select sid,name,replace(brief,"李洪志","***") from psd_
把学生表中,简介字段中的李洪志换成“***”
update psd_student set brief=replace(brief,"李洪志","***");
concate(字段名,"string",.....)
作用:字符串连接
特点:遇到NULL返回null
&& &查询语句的字段列表
&& &update语句的 字段名=值,在值位置出现
&& &1、把name和sex连接
&& &2、把name sex brief 三个字段的内容连接,连接后写入到brief字段&& &
&& &update psd_student set brief=concat(name,"|",sex,"|",brief);
时间日期函数
文章表(id,title,content,num,addtime datetime)
insert语句中使用
insert into news(title,content,addtime) values("tt","cc",now())
from_unixtime(字段|时间戳,"时间日期格式")
作用:对时间戳,转化成时间日期格式
时间日期格式:
"%Y-%m-%d %H:%i:%s"
"%Y-%m-%d"
"%H:%i:%s"
&& &文章表(id,title,content,num,addtime int(11))
select id,title,from_unixtime(addtime,"%Y-%m-%d %H:%i:%s") from news where id=1;
create table news(
&& &id int(8) primary key auto_increment,
&& &title char(100) not null,
&& &content text,
&& &num int(6) default 0,
&& &addtime int(11)
本文来自:绵阳史安平个人博客.励志于每一位朋友
欢迎转载,转载请注明本文链接:
/arc-137.html
猜你也喜欢的:}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信