一个困扰了我三天的SQL优化问题。(多条数据取最近的数据)

2024-09-04 19:58

本文主要是介绍一个困扰了我三天的SQL优化问题。(多条数据取最近的数据),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

            由于优化的方向不对,一个SQL困扰了我好几天,物化视图什么之类的,全部都试过了,还是没有解决。今天,在看这个问题的时候,灵光一现,咦,好像是这里有问题,然后改了一下,终于解决了。这个SQL,从最初的16秒,后面换了各种方法,有180秒,150秒,60多秒,试过了各种SQL,终于,优化到了0.3秒。好了,现在说下问题。

           这个SQL总共涉及了6张表,其实最主要的是做数据的统计。直接看SQL吧。

1.这个是最初的:速度是16秒。

SELECT
*
FROM
(
SELECT
A . ID,
warehousecode,
sku,
OWNER,
enname,
customername,
createtime,
(startnum + changenum) sumnum,
(startnum + changenum - locknum) availablenum,
locknum
FROM
(
SELECT
t1. ID,
t2.warehousecode,
t1.sku,
C . NAME customername,
t1.createtime,
t1. OWNER,
P .cnname enname,
(
NUMBER + COALESCE (locknumber, 0)
) startnum,
(
SELECT
COALESCE (
SUM (
(
CASE
WHEN TYPE = 'inbound' THEN
qty
ELSE
(- 1 * qty)
END
)
),
0
) AS qty
FROM
t_inventory_change tc
WHERE
tc.warehousecode = t2.warehousecode
AND tc. OWNER = t1. OWNER
AND tc.sku = t1.sku
AND tc.createtime > t1.createtime
) changeNum,
(
SELECT
COALESCE (SUM(qty), 0)
FROM
t_inventory_lock tl
WHERE
VALID = 't'
AND tl.warehousecode = t2.warehousecode
AND tl. OWNER = t1. OWNER
AND tl.sku = t1.sku
AND tl.createtime > t1.createtime
) lockNum
FROM
t_inventory_detail t1
LEFT JOIN t_inventory t2 ON t1.inventoryid = t2. ID
LEFT JOIN t_product P ON P . OWNER = t1. OWNER
AND P .status = 1
AND P .sku = t1.sku
LEFT JOIN t_customer C ON C .code = t1. OWNER
WHERE
t1.createtime = (
SELECT
MAX (t3.createtime)
FROM
t_inventory_detail t3,
t_inventory t4
WHERE
t3.inventoryid = t4. ID
AND t2.warehousecode = t4.warehousecode
AND t1.sku = t3.sku
)

) AS A
) AS T
WHERE
1 = 1
order by createtime desc


2.这个是 160 秒的

select DISTINCT t.*
,(NUMBER + COALESCE (locknumber, 0) + changenum) sumnum
,(NUMBER + COALESCE (locknumber, 0) + changenum - locknum) availablenum 
from(
select td.sku,td.warehousecode,td.owner,td.cnname,td.number,td.locknumber,td.createtime,
c.name customername,
p.cnname enname,
COALESCE(SUM(CASE WHEN tc.TYPE = 'inbound' THEN tc.qty ELSE (- 1 * tc.qty) END ) OVER(partition by tc.warehousecode,tc.OWNER,tc.sku),0) changenum,
COALESCE(SUM(tl.qty) OVER(partition by tl.warehousecode,tl.OWNER,tl.sku),0) lockNum
from(
select sku,warehousecode,owner,cnname,number,locknumber,createtime from(
select t1.sku,t2.warehousecode,t1.owner,t1.cnname,t1.number,t1.locknumber,t1.createtime,
row_number() over(partition by t1.sku,t1.owner,t2.warehousecode order by t1.createtime desc) rn 
from t_inventory_detail t1 left join t_inventory t2 on t1.inventoryid=t2.id) t where rn=1) td
left join t_product p on p.owner = td.owner and p.status = 1 and p .sku = td.sku
left join t_customer c on c.code = td.owner
left join t_inventory_lock tl on tl.warehousecode = td.warehousecode AND tl. OWNER = td. OWNER AND tl.sku = td.sku AND tl.createtime > td.createtime and VALID = 't' 
left join t_inventory_change tc on tc.warehousecode = td.warehousecode AND tc. OWNER = td. OWNER AND tc.sku = td.sku AND tc.createtime > td.createtime
) t;


3.这个是0.3秒的

SELECT
*
FROM
(
SELECT
A . ID,
warehousecode,
sku,
OWNER,
enname,
customername,
createtime,
(startnum + changenum) sumnum,
(startnum + changenum - locknum) availablenum,
locknum
FROM
(
SELECT
td. ID,
td.warehousecode,
td.sku,
C . NAME customername,
td.createtime,
td. OWNER,
P .cnname enname,
(
NUMBER + COALESCE (locknumber, 0)
) startnum,
(
SELECT
COALESCE (
SUM (
(
CASE
WHEN TYPE = 'inbound' THEN
qty
ELSE
(- 1 * qty)
END
)
),
0
) AS qty
FROM
t_inventory_change tc
WHERE
tc.warehousecode = td.warehousecode
AND tc. OWNER = td. OWNER
AND tc.sku = td.sku
AND tc.createtime > td.createtime
) changeNum,
(
SELECT
COALESCE (SUM(qty), 0)
FROM
t_inventory_lock tl
WHERE
VALID = 't'
AND tl.warehousecode = td.warehousecode
AND tl. OWNER = td. OWNER
AND tl.sku = td.sku
AND tl.createtime > td.createtime
) lockNum
FROM
(
SELECT
T . ID,
sku,
warehousecode,
OWNER,
cnname,
NUMBER,
locknumber,
createtime
FROM
(
SELECT
t1. ID,
t1.sku,
t2.warehousecode,
t1. OWNER,
t1.cnname,
t1. NUMBER,
t1.locknumber,
t1.createtime,
ROW_NUMBER () OVER (
PARTITION BY t1.sku,
t1. OWNER,
t2.warehousecode
ORDER BY
t1.createtime DESC
) rn
FROM
t_inventory_detail t1
LEFT JOIN t_inventory t2 ON t1.inventoryid = t2. ID
) T
WHERE
rn = 1
) td

LEFT JOIN t_product P ON P . OWNER = td. OWNER
AND P .status = 1
AND P .sku = td.sku
LEFT JOIN t_customer C ON C .code = td. OWNER
) AS A
) AS T
WHERE
1 = 1
 order by createtime desc


其实最主要的问题,还是出在红色标记的区别。就是有多个数据的时候,取最近的数据。最开始以为这里没有问题,一直以为是子查询的问题,后面发现并不是子查询的问题。记在这里,给自己一个教训。

这篇关于一个困扰了我三天的SQL优化问题。(多条数据取最近的数据)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136885

相关文章

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

MySQL中时区参数time_zone解读

《MySQL中时区参数time_zone解读》MySQL时区参数time_zone用于控制系统函数和字段的DEFAULTCURRENT_TIMESTAMP属性,修改时区可能会影响timestamp类型... 目录前言1.时区参数影响2.如何设置3.字段类型选择总结前言mysql 时区参数 time_zon

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

Oracle数据库使用 listagg去重删除重复数据的方法汇总

《Oracle数据库使用listagg去重删除重复数据的方法汇总》文章介绍了在Oracle数据库中使用LISTAGG和XMLAGG函数进行字符串聚合并去重的方法,包括去重聚合、使用XML解析和CLO... 目录案例表第一种:使用wm_concat() + distinct去重聚合第二种:使用listagg,