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
执行所需时间:
代码简化前耗费时间:
由此可见,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)
count(1)函数,如果表中有索引的话,会自动使用索引字段进行查询;
如果没有额外创建索引的话,会自动使用主键索引字段进行查询;(主键是唯一索引)
如果对没有索引的字段进行计数的话,就会全表执行。
没有使用这种方式的必要,还浪费时间。
关于索引
如上面所示,要进行分组查询的表,一共有1163万条数据;
分组和查询的字段必须得走索引,如果不添加索引的话,那得查到什么时候?(数据少的话,有没有索引或者走不走索引都无所谓)