请教一个sql查询问题,可能要用到2次count和2次groupby

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教一个sql查询问题,可能要用到2次count和2次groupby相关的知识,希望对你有一定的参考价值。

我举例一下:
表一:voucher表
会计期间,凭证号
200506,A0001
200506,A0002
200506,A0003
200507,A0004
200507,A0005

表二:details表
凭证号,明细号
A0001,M0001
A0001,M0002
A0002,M0003
A0003,M0004
A0003,M0005
A0003,M0006
A0004,M0007
A0004,M0008
A0005,M0009
A0005,M0010
A0005,M0011
A0005,M0012
A0005,M0013

如果我用sql语句查询
select 会计期间,count(*)
from voucher group by 会计期间
order by 会计期间
结果如下:
会计期间,凭证数量汇总
200506,3
200507,2

如果我用sql语句查询
select v.会计期间,count(*)
from voucher v, details d
where v.凭证号=d.凭证号
group by v.会计期间
order by v.会计期间
结果如下:
会计期间,明细数量汇总
200506,6
200507,7

现在问题来了,查询着2个结果需要2个sql语句。
有没有一个select语句,能够实现会计期间,凭证数量汇总,明细数量汇总一次查询的情况?

需要的结果如下:
会计期间,凭证数量汇总,明细数量汇总
200506,3,6
200507,2,7

参考技术A 这个不难啊,可以直接把这两个结果连起来啊,把查询的结果作为一个临时视图
select * from
(select 会计期间 temp1time,count(*)
from voucher group by 会计期间
order by 会计期间 )temp1 ,
(select v.会计期间 temp2time,count(*)
from voucher v, details d
where v.凭证号=d.凭证号
group by v.会计期间
order by v.会计期间 )temp2 where temp1time=temp2time本回答被提问者采纳
参考技术B SELECT b.凭证号,count(1),m_c FROM (SELECT 凭证号,count(1)as m_c FROM details group by 凭证号) A,voucher B
WHERE A.凭证号=b.凭证号
group by b.凭证号,mc
参考技术C select a.kjqj as '会计期间',a.sm as '凭证数量汇总',b.sm as '明细数量汇总'
from
(
select kjqj,count(*) as sm
from #voucher
group by kjqj
) a
left join
(
select kjqj,count(*) as sm
from(
select a.*,b.mxh
from #voucher a left join #details b
on a.pzh=b.pzh
) a
group by kjqj

) b
on a.kjqj=b.kjqj

兄弟 我那 表是创建的临时表 ,如果你用直接在你的库上把表明替换掉,就可以了 ,我在我的库上次是过了 ,可以得到你想要的结果,如果有疑问可以随时问我, KJQJ 表示会计期间 ,PZH 表示 凭证号,MXH 表示 明细好
参考技术D 哎!我也是新手!什么时候才能运用自如啊??

高并发场景案例分享count实时查询之坑

上一篇主要从设计层面,分享了一些小经验。

因软件系统有其复杂性和多样性,不同的场景、架构下,系统的瓶颈各不相同。

文章里的一些想法和设计并不通用,主要针对的是高并发场景下海量数据的实时查询。


 

这次再分享一个更贴近生活的案例。

有时看似简单的逻辑,往往隐藏了最深的坑,甚至成为系统的性能瓶颈。

举个栗子

微博用户主页

这个页面应该都不陌生,业务也并不复杂。

值得注意的是红线圈出的功能:粉丝数量,微博总数,评论、转发、点赞数量。

乍一看很简单,再一看还是很简单。

根据条件,从相关的业务表统计数量就好了呀。

比如, 从好友关系表count所有关注作者的人( type = 2 代表被关注)。

select count(1) from user_relation where uid = \'xxx\' and type = 2 

没毛病啊,十分合理。这么简单的东西难道还能玩出花来?

第一版上线时

我就是这么做的,结果整个服务直接挂掉了。

看了下监控,发现量变竟然引发了质变。

在系统数据量不大或流量不高时,使用count查询来处理此业务没有任何问题。

当数据达到一定量级时,比如图中的粉丝量300W+,如果查询的结果集数量过大,即便根据索引查询,正常耗时也会达到几秒、十几秒,更别说在高并发下频繁查询。

用户主页,一页查询15条动态,每条动态都要显示转发、评论、点赞数,总共需要count45次。

再加上微博上亿的用户量,超高的并发,此处若实时地使用count查询,将轻松GET以下异常:

The last packet sent successfully to the server was 5,652 milliseconds ago

因为MySQL服务器所有的线程都用来执行这些count慢查询了,导致后面的请求全部阻塞。

此时,数据库性能监控面板会有一些显著的指标特征:CPU负载达到100%,运行线程数异常高。

第二版上线时

我专门加了一张表用来计数, 类似 (动态id, 点赞数, 评论数, 转发数 )这样的结构。

每次用户点赞、评论、转发时,直接在表上写入数量+1。

查询时直接从此表读取数量,避免count查询。

解决方法虽简单了些,能搞定性能上的瓶颈即可。

此前,也参考过一些关于微博架构的资料,里面有提到计数器服务。(如:https://www.cnblogs.com/kenshinobiy/p/4316217.html。)

但当时并没理解为什么要做计数器?什么数这么吊还要专门做个服务来计算?

微信朋友圈

微信朋友圈

朋友圈的设计,就完全不用展示数量。

直接避开了很多可能给系统带来性能瓶颈的坑。

相比之下,微信的工程师一定能少掉不少头发。

当然,二者社交场景不同,介质也不同(WEB | APP),有些产品上的设计是不可避免的。

综上

在MySQL进行实时查询时,应该避免查询出的结果集数量过大。

否则,即使像count这样最简单的查询语句,也可能带来性能问题。

当然,最终还是要看具体的使用场景。

比如,一个用来汇总每日报表的查询语句,使用了 union,group by  等性能不佳的子句,整个查询耗时5秒。

但它每天只执行一次,且查询的数据表并不频繁使用。即便这是一条慢查询,对性能的影响也是微乎其微。

而像案例中的count语句,即便耗时只有1秒,如果每秒请求1000次,那它对数据库CPU的消耗就是前者的200倍。


 

以上是关于请教一个sql查询问题,可能要用到2次count和2次groupby的主要内容,如果未能解决你的问题,请参考以下文章

请教数据库高手,在access2003里,用sql语句查询实现两表关联查询用count更新其中一表?

sql 语句 count 使用请教

COUNT(*) 小于 2 的 SQL 更新

请问,如何用一条SQL查询出分页的数据和总记录数啊?MySQL的!不用存储

请教ThinkPHP为啥会这么容易数据库查询超时

SQL 查询每个月统计的数据。