首页 > 数据库 >mysql、oracle 分组查询,每组取一条数据

mysql、oracle 分组查询,每组取一条数据

时间:2023-02-14 10:00:50浏览次数:44  
标签:索引 每组 t2 t3 查询 cz ORGID mysql oracle

1.情景展示

有这样一种需求:

将数据按照机构进行分组,然后取每个机构下只取一条记录,如何实现?

2.mysql

分组查询出来某字段,然后和原来的表进行关联查询。

方式一:通过内连接来实现

查看代码

SELECT
t3.INVOICINGPARTYCODE,
t3.INVOICINGPARTYNAME,
t2.EINVOICECODE,
t2.EINVOICENUMBER,
t2.CARDNO,
t2.PAYERPARTYCODE,
t2.PAYERPARTYNAME
FROM
(
SELECT
ORGID,
max( ID ) ID
FROM
cz_fet_main_mz
WHERE
CARDTYPE = 01
AND LENGTH( CARDNO )= 18
AND KPSTATUS = 1
AND DATE_FORMAT( ISSUETIME, '%Y' )= '2021'
GROUP BY
ORGID
) t,
cz_fet_main_mz t2,
cz_unitinfo t3
WHERE
t2.ORGID = t.ORGID
AND t2.ID = t.ID
AND t3.ORGCODE = t2.ORGID
ORDER BY
t3.CHECKCODE

这里有两个核心点:

第一,分组查询出来的字段,需要确保该字段在表中必须具有数据唯一性,不然的话,分组查询没有意义;

比方说:时间,但时间也有可能重复,如果我们只精确到秒的话(毫秒也可能会重);

如果表中没有定义唯一性字段,且确实不知道那个字段具有唯一性,最简单的方式就是表主键(表主键本身就具有唯一性)。

第二,将查询结果当做一张表,来和之前的表建立内连接。

上面的代码,其实还可以进行简化:

ORGID字段可以去掉,即:

查看代码

SELECT
t3.INVOICINGPARTYCODE,
t3.INVOICINGPARTYNAME,
t2.EINVOICECODE,
t2.EINVOICENUMBER,
t2.CARDNO,
t2.PAYERPARTYCODE,
t2.PAYERPARTYNAME
FROM
(
SELECT
max( ID ) ID
FROM
cz_fet_main_mz
WHERE
CARDTYPE = 01
AND LENGTH( CARDNO )= 18
AND KPSTATUS = 1
AND DATE_FORMAT( ISSUETIME, '%Y' )= '2021'
GROUP BY
ORGID
) t,
cz_fet_main_mz t2,
cz_unitinfo t3
WHERE
T2.ID = T.ID
AND t3.ORGCODE = t2.ORGID
ORDER BY
t3.CHECKCODE

执行所需时间:

mysql、oracle 分组查询,每组取一条数据_mysql

代码简化前耗费时间:

mysql、oracle 分组查询,每组取一条数据_主键_02

由此可见,SQL不是越简化越快(另外,重复的where限制条件,加上也并不能提高查询速度)。

方式二:通过exits来实现

查看代码

SELECT
t3.INVOICINGPARTYCODE,
t3.INVOICINGPARTYNAME,
t2.EINVOICECODE,
t2.EINVOICENUMBER,
t2.CARDNO,
t2.PAYERPARTYCODE,
t2.PAYERPARTYNAME
FROM
cz_fet_main_mz t2,
cz_unitinfo t3
WHERE
t3.ORGCODE = t2.ORGID
AND EXISTS (
SELECT
1
FROM
cz_fet_main_mz
WHERE
CARDTYPE = 01
AND LENGTH( CARDNO )= 18
AND KPSTATUS = 1
AND DATE_FORMAT( ISSUETIME, '%Y' )= '2021'
GROUP BY
ORGID
HAVING
ORGID = t2.ORGID
AND INVOICENO = t2.INVOICENO
)
ORDER BY
t3.CHECKCODE

使用exists()从逻辑上应该是行得通的,但是,我并没有测试出来这种方式的真实性。

原因在于:数量太大,查询结果太慢,用了700多秒还没执行完,所以,放弃了;

如果你的数据量小的话,可以试试看,如果可行的话,欢迎在评论区留言,我替大家谢谢你。

3.oracle

内连接的语法与mysql一致,这里不再赘述。

4.扩展

关于计数查询count(1)

mysql、oracle 分组查询,每组取一条数据_分组查询_03

count(1)函数,如果表中有索引的话,会自动使用索引字段进行查询;

如果没有额外创建索引的话,会自动使用主键索引字段进行查询;(主键是唯一索引)

mysql、oracle 分组查询,每组取一条数据_字段_04

如果对没有索引的字段进行计数的话,就会全表执行。

mysql、oracle 分组查询,每组取一条数据_mysql_05

没有使用这种方式的必要,还浪费时间。

关于索引

如上面所示,要进行分组查询的表,一共有1163万条数据;

分组和查询的字段必须得走索引,如果不添加索引的话,那得查到什么时候?(数据少的话,有没有索引或者走不走索引都无所谓)

写在最后

  哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!



作者:Marydon

标签:索引,每组,t2,t3,查询,cz,ORGID,mysql,oracle
From: https://blog.51cto.com/u_15964717/6055571

相关文章

  • MySQL 8.0 修改root远程登录【ERROR 1410 (42000): You are not allowed to create a
    MySQL8.0的数据库root用户默认无法远程登录,需要修改root的远程授权,如下:mysql>grantallprivilegeson*.*to'root'@'%';ERROR1410(42000):Youarenotallowed......
  • (数据库系统概论|王珊)第三章关系数据库标准语言SQL-第零节:MYSQL环境安装和表的建立以及
    pdf下载:密码7281专栏目录首页:【专栏必读】(考研复试)数据库系统概论第五版(王珊)专栏学习笔记目录导航及课后习题答案详解目录一:注意事项二:MYSQL环境(1)下载(2)安装(3)MYSQL可视......
  • 12. Oracle的初始化参数和性能视图
    一.性能参数1.CPUparametercpu_count:显示的是逻辑cpu数量(thread),主要是对并行度有影响2.Memoryparameterpga_aggregate_target:可以自动对pga进行调......
  • [Oracle19C ASM管理] ASM的网络服务
    启用了ASM集群以后,网络管理放给了grid用户。grid用户的$ORACLE_HOME/network/admin有网络配置文件,而oracle用户下的网络配置文件则不存在了。[[email protected]......
  • mysql 创建库和表
    数据库创建数据库查看数据库删除数据库数据表创建表查看表删除表清除表数据数据库创建数据库语法CREATEDATABASE[IFNOTEXISTS]<数据库名>[[DEFA......
  • MySQL基础
    基础篇通用语法及分类DDL:数据定义语言,用来定义数据库对象(数据库、表、字段)DML:数据操作语言,用来对数据库表中的数据进行增删改DQL:数据查询语言,用来查询数据库中......
  • [Oracle19C ASM管理] ASM服务的启停
    自动方式启停crsctlstatres-t查看ASM服务的状态,it'sokthatora.ons和ora.diskmon是OFFLINE[[email protected]:/home/grid]$crsctlstatres-t------......
  • node mysql 增删改查 demo
    前端原生jsJquery后端Node数据库MySQL​​​http://hongbin.xyz:8080/​​​​github仓库​​​​演示视频地址​​node增删改查TODO:删除用户数据库需要触发器将......
  • 关于我忘记MySQL root 密码那件事
    登录MySQL时,忘记密码,百度一番找到合适的方法问题已解决,记录一下。该篇文章仅做学习用,方便自己下次查找。1、先把MySQL的服务为停了,可以直接按win键搜服务,找到MySQL服务,......
  • mysql查询语句case及时间操作
    1、获取系统当前时间戳SELECT unix_timestamp(now())*1000 --乘以1000,为了得到毫秒时间戳   2、时间戳转年月日SELECTFROM_UNIXTIME(1676280033000/1000,......