一、问题发现:

主查询功能发现两条一样的记录,但是审批状态不一样,一个已通过,一个待审核

主表付款表:

CREATE TABLE `pur_or_payment` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '系统编码 初始值为“1”',
`pa_code` varchar(32) NOT NULL COMMENT '付款编号',
`pa_serv_ident` varchar(12) NOT NULL DEFAULT 'SN070201' COMMENT '付款业务走向',
`sys_ar_cu_id` int(11) NOT NULL COMMENT '订单供应商',
`pur_or_pp_id` varchar(255) NOT NULL COMMENT '条款id (多选)',
`pa_amount` decimal(20,10) NOT NULL COMMENT '付款金额',
`pa_state` char(1) NOT NULL COMMENT '付款状态 付款中,已付款',
`pa_date` datetime DEFAULT NULL COMMENT '付款日期',
`creator` varchar(32) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='订单付款表';

主表关联了两张副表,两张副表也是张业务表

CREATE TABLE `fin_ex_apply` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '系统编码 主键,初始值为“10000001”',
`ap_code` varchar(14) NOT NULL COMMENT '单据编码',
`sys_ar_co_id` int(11) NOT NULL COMMENT '所属公司 引用表<公司档案> ',
`sys_ar_de_id` int(11) NOT NULL COMMENT '申请部门 引用表<部门档案> ',
`ap_serv_id` int(11) DEFAULT NULL COMMENT '其它业务id',
`ap_serv_ident` varchar(32) DEFAULT NULL COMMENT '业务来源标识',
`ap_date` datetime NOT NULL COMMENT '申请日期',
`ap_proposer` varchar(32) NOT NULL COMMENT '申请人 引用表<员工档案>',
`ap_ro_type` varchar(32) NOT NULL COMMENT '往来对象类型 related object',
`ap_re_obj` int(11) NOT NULL COMMENT '往来对象 <员工档案><客商档案>',
`ap_remark` text COMMENT '申请备注',
`ap_de_amount` decimal(11,2) NOT NULL COMMENT '冲账金额 deduct amount',
`ap_pa_amount` decimal(11,2) NOT NULL COMMENT '付款金额 payment amount',
`ap_to_amount` decimal(11,2) NOT NULL COMMENT '合计金额 total amount',
`ap_sett_meth` varchar(32) DEFAULT NULL COMMENT '引用内置<结算方式> settlement method',
`ap_pa_remark` varchar(255) DEFAULT NULL COMMENT '付款备注 payment remark',
`ap_re_payee` varchar(32) NOT NULL COMMENT '收款人 payee',
`ap_re_account` varchar(32) NOT NULL COMMENT '收款账号 receive account',
`ap_re_ba_name` varchar(64) NOT NULL COMMENT '收款银行 recevie bank',
`ap_re_subbranch` varchar(64) DEFAULT NULL COMMENT '收款支行',
`ap_re_ba_locus` varchar(128) NOT NULL COMMENT '开户行所在地',
`ap_appr_state` char(1) NOT NULL COMMENT '审核状态 0审核中 1已审核 2不通过',
`ap_appr_date` datetime DEFAULT NULL COMMENT '审核日期',
`creator` varchar(32) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`updator` varchar(32) NOT NULL COMMENT '更新人',
`update_time` datetime NOT NULL COMMENT '更新时间',
`status` char(1) NOT NULL COMMENT '记录状态 1正常,0删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10000069 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='报销申请表'; CREATE TABLE `fin_sp_apply` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '系统编码 主键,初始值为“10000001”',
`ap_code` varchar(14) NOT NULL COMMENT '单据编码',
`sys_ar_co_id` int(11) NOT NULL COMMENT '所属公司 引用表<公司档案> ',
`sys_ar_de_id` int(11) NOT NULL COMMENT '申请部门 引用表<部门档案> ',
`ap_serv_id` int(11) DEFAULT NULL COMMENT '其它业务id',
`ap_serv_ident` varchar(32) DEFAULT NULL COMMENT '业务来源标识',
`ap_date` datetime NOT NULL COMMENT '申请日期',
`ap_proposer` varchar(32) NOT NULL COMMENT '申请人 引用表<员工档案>',
`ap_ro_type` varchar(32) NOT NULL COMMENT '往来对象类型 选择:单位/员工',
`ap_re_obj` int(11) NOT NULL COMMENT '往来对象 引用表<客商档案><员工档案>',
`ap_remark` text COMMENT '申请备注',
`ap_to_amount` decimal(11,2) NOT NULL COMMENT '合计金额 total',
`ap_sett_meth` varchar(32) NOT NULL COMMENT '付款结算方式 引用内置<付款结算方式> settlement method',
`ap_pa_remark` varchar(255) NOT NULL COMMENT '付款备注',
`ap_re_payee` varchar(32) NOT NULL COMMENT '收款人',
`ap_re_account` varchar(32) NOT NULL COMMENT '收款账号',
`ap_re_bank` varchar(64) NOT NULL COMMENT '收款银行',
`ap_re_subbranch` varchar(64) DEFAULT NULL COMMENT '收款支行',
`ap_re_ba_locus` varchar(128) NOT NULL COMMENT '开户行所在地',
`ap_appr_state` char(1) DEFAULT NULL COMMENT '审核状态 0审核中 1已审核 2不通过',
`ap_appr_date` datetime DEFAULT NULL COMMENT '审核日期',
`creator` varchar(32) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`updator` varchar(32) NOT NULL COMMENT '更新人',
`update_time` datetime NOT NULL COMMENT '更新时间',
`status` char(1) NOT NULL COMMENT '记录状态 1正常,0删除',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `ap_code` (`ap_code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10000032 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用款申请信息表';

  

二、问题排查

两个重复记录的明细和表单更新访问都是报错,错误日志显示,查询到了多条记录

错误定位到查询SQL上:

SELECT
pa.*,
cu.cu_name AS cuName,
cu.cu_code AS cuCode,
us.us_name AS creatorName,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.ap_appr_state
WHEN 'SN070101' THEN ex.ap_appr_state
ELSE ex.ap_appr_state
END AS apApprState,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.id
WHEN 'SN070101' THEN ex.id
ELSE sp.id
END AS paServId,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN '用款申请'
WHEN 'SN070101' THEN '费用报销'
ELSE '用款申请'
END AS paServIdentName
FROM
pur_or_payment AS pa
LEFT JOIN fin_sp_apply AS sp ON pa.id = sp.ap_serv_id AND pa.pa_serv_ident = 'SN070201'
LEFT JOIN fin_ex_apply AS ex ON pa.id = ex.ap_serv_id AND pa.pa_serv_ident = 'SN070101'
LEFT JOIN sys_ar_customer AS cu ON cu.id = pa.sys_ar_cu_id
LEFT JOIN sys_pr_user AS us ON us.us_username = pa.creator

  

定位到问题记录上的SQL结果是这样:

发现单号BX231100193也被加入进来了

所以定位到SQL条件就在这两段:

 LEFT JOIN fin_sp_apply AS sp ON pa.id = sp.ap_serv_id AND pa.pa_serv_ident = 'SN070201'
LEFT JOIN fin_ex_apply AS ex ON pa.id = ex.ap_serv_id AND pa.pa_serv_ident = 'SN070101'   

第二个条件不生效,BX231100193是销售合同的,要筛选采购订单的,显然条件未生效

三、问题排查

同事认为第二个条件还是在以主表的记录内进行筛选,并没有涉及到副表的筛选

才导致重复记录的出现,所以解决办法是转换成副表的筛选条件

 LEFT JOIN fin_sp_apply AS sp ON pa.id = sp.ap_serv_id AND pa.pa_serv_ident = 'SN070201'
LEFT JOIN fin_ex_apply AS ex ON pa.id = ex.ap_serv_id AND pa.pa_serv_ident = 'SN070101'    更改为 LEFT JOIN fin_sp_apply AS sp ON pa.id = sp.ap_serv_id AND sp.ap_serv_ident = 'SN050104'
LEFT JOIN fin_ex_apply AS ex ON pa.id = ex.ap_serv_id AND ex.ap_serv_ident = 'SN050104'

  

查询后发现,BX231100193单号已经过滤,结果正确

四、本地环境复盘

担心只是巧合,在本地开发环境进行复现

以费用报销的一张单据为例:

SELECT
pa.pa_code,
pa.pa_serv_ident,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.ap_code
WHEN 'SN070101' THEN ex.ap_code
ELSE ''
END AS apCode,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.ap_appr_state
WHEN 'SN070101' THEN ex.ap_appr_state
ELSE ex.ap_appr_state
END AS apApprState,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.id
WHEN 'SN070101' THEN ex.id
ELSE sp.id
END AS paServId,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN '用款申请'
WHEN 'SN070101' THEN '费用报销'
ELSE '用款申请'
END AS paServIdentName
FROM
pur_or_payment AS pa
LEFT JOIN fin_sp_apply AS sp ON pa.id = sp.ap_serv_id AND pa.pa_serv_ident = 'SN070201'
LEFT JOIN fin_ex_apply AS ex ON pa.id = ex.ap_serv_id AND pa.pa_serv_ident = 'SN070101'
LEFT JOIN sys_ar_customer AS cu ON cu.id = pa.sys_ar_cu_id
LEFT JOIN sys_pr_user AS us ON us.us_username = pa.creator
WHERE pa_code = 'DF24030001'
ORDER BY pa_code DESC; +------------+---------------+-------------+-------------+----------+-----------------+
| pa_code | pa_serv_ident | apCode | apApprState | paServId | paServIdentName |
+------------+---------------+-------------+-------------+----------+-----------------+
| DF24030001 | SN070101 | BX240300001 | 3 | 10000063 | 费用报销 |
+------------+---------------+-------------+-------------+----------+-----------------+
1 rows in set (0.08 sec)

  

单据编号为 BX240300001,根据这张单据我们创建一条”重复记录“

单据编号为 BX340300001,但是业务类别为”销售合同“

INSERT INTO `fin_ex_apply`  VALUES (NULL, 'BX340300001', 1003, 10000021, 8, 'SN030601', '2024-03-19 10:24:03', ....); -- 后面信息省略

  

再次查询,问题复现,出现两条相同记录:

mysql> SELECT
pa.pa_code,
pa.pa_serv_ident,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.ap_code
WHEN 'SN070101' THEN ex.ap_code
ELSE ''
END AS apCode,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.ap_appr_state
WHEN 'SN070101' THEN ex.ap_appr_state
ELSE ex.ap_appr_state
END AS apApprState,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.id
WHEN 'SN070101' THEN ex.id
ELSE sp.id
END AS paServId,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN '用款申请'
WHEN 'SN070101' THEN '费用报销'
ELSE '用款申请'
END AS paServIdentName
FROM
pur_or_payment AS pa
LEFT JOIN fin_sp_apply AS sp ON pa.id = sp.ap_serv_id AND pa.pa_serv_ident = 'SN070201'
LEFT JOIN fin_ex_apply AS ex ON pa.id = ex.ap_serv_id AND pa.pa_serv_ident = 'SN070101'
LEFT JOIN sys_ar_customer AS cu ON cu.id = pa.sys_ar_cu_id
LEFT JOIN sys_pr_user AS us ON us.us_username = pa.creator
WHERE pa_code = 'DF24030001'
ORDER BY pa_code DESC; +------------+---------------+-------------+-------------+----------+-----------------+
| pa_code | pa_serv_ident | apCode | apApprState | paServId | paServIdentName |
+------------+---------------+-------------+-------------+----------+-----------------+
| DF24030001 | SN070101 | BX240300001 | 3 | 10000063 | 费用报销 |
| DF24030001 | SN070101 | BX340300001 | 3 | 10000068 | 费用报销 |
+------------+---------------+-------------+-------------+----------+-----------------+
2 rows in set (0.09 sec)

  

改用修正后的SQL:

mysql> SELECT
pa.pa_code,
pa.pa_serv_ident,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.ap_code
WHEN 'SN070101' THEN ex.ap_code
ELSE ''
END AS apCode,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.ap_appr_state
WHEN 'SN070101' THEN ex.ap_appr_state
ELSE ex.ap_appr_state
END AS apApprState,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN sp.id
WHEN 'SN070101' THEN ex.id
ELSE sp.id
END AS paServId,
CASE pa.pa_serv_ident
WHEN 'SN070201' THEN '用款申请'
WHEN 'SN070101' THEN '费用报销'
ELSE '用款申请'
END AS paServIdentName
FROM
pur_or_payment AS pa
LEFT JOIN fin_sp_apply AS sp ON pa.id = sp.ap_serv_id AND sp.ap_serv_ident = 'SN050104'
LEFT JOIN fin_ex_apply AS ex ON pa.id = ex.ap_serv_id AND ex.ap_serv_ident = 'SN050104'
LEFT JOIN sys_ar_customer AS cu ON cu.id = pa.sys_ar_cu_id
LEFT JOIN sys_pr_user AS us ON us.us_username = pa.creator
WHERE pa_code = 'DF24030001'
ORDER BY pa_code DESC;
+------------+---------------+-------------+-------------+----------+-----------------+
| pa_code | pa_serv_ident | apCode | apApprState | paServId | paServIdentName |
+------------+---------------+-------------+-------------+----------+-----------------+
| DF24030001 | SN070101 | BX240300001 | 3 | 10000063 | 费用报销 |
+------------+---------------+-------------+-------------+----------+-----------------+
1 row in set (0.04 sec)

  

  

【MySQL】LEFT JOIN 踩坑的更多相关文章

  1. Ubuntu 16.04 安装Mysql 5.7 踩坑小记

    title:Ubuntu 16.04 安装Mysql 5.7 踩坑小记 date: 2018.02.03 安装mysql sudo apt-get install mysql-server mysql ...

  2. 【详记MySql问题大全集】四、设置MySql大小写敏感(踩坑血泪史)

    系列目录 一.安装MySql 二.安装并破解Navicat 三.没有my.in配置文件怎么办 四.设置MySql的大小写敏感 五.重置MySql登陆密码 这一篇可以说是我的踩坑的血泪史了... MyS ...

  3. MySQL切换版本踩坑记录(包括恢复数据方法)

    踩坑起因:在创建数据库时, 字段:create_time datetime DEFAULT CURRENT_TIMESTAMP, 报异常--Error Code: 1067 - Invalid def ...

  4. SparkR链接mysql数据库(踩坑)

    本文主要讲述sparkR链接Mysql的过程和坑. SparkR的开发可以用RStudio工具进行开发,连接spark可以通过RStudio界面中的Connections进行配置连接;具体方法这里不做 ...

  5. Linux下部署MySQL,大小写敏感踩坑记录

    今天在将开发环境中的门户数据库复制到新环境后,使用SqlSugar的ORM框架进行数据库操作的时候,出现了主键找不到的现象.排查了很久终于发现了关键点.特此记录. 1.开发环境:    操作系统:CE ...

  6. Spark踩坑记——共享变量

    [TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ...

  7. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  8. MySQL 5.7版本安装教程-踩坑总结

    下载 MySQL下载地址 选择下载64位(看自己电脑是32位还是64位) 点击下载之后,它会让你登录,没有Oracle账户,跟着它的步骤注册一个就好了. 安装 打开下载好的压缩包解压到你的某一目录下, ...

  9. 【踩坑记录】记一次MySQL主从复制延迟的坑

    最近开发中遇到的一个MySQL主从延迟的坑,记录并总结,避免再次犯同样的错误. 情景 一个活动信息需要审批,审批之后才能生效.因为之后活动要编辑,编辑后也可能触发审批,审批中展示的是编辑前的活动内容, ...

  10. CentOS7.4安装MySQL踩坑记录

    CentOS7.4安装MySQL踩坑记录 time: 2018.3.19 CentOS7.4安装MySQL时网上的文档虽然多但是不靠谱的也多, 可能因为版本与时间的问题, 所以记录下自己踩坑的过程, ...

随机推荐

  1. Opencv笔记(12)傅里叶变换

    在之前了解的OpenCV为我们实现的图像变换,这些本质上是从图像到输出图像的映射,即输入仍是一幅图像.本章的傅里叶变换,输出数组的值在含义上和原图像的强度值大不相同,是输入图像的频域表示. cv::d ...

  2. 算法金 | 再见,PCA 主成分分析!

    ​大侠幸会,在下全网同名[算法金] 0 基础转 AI 上岸,多个算法赛 Top [日更万日,让更多人享受智能乐趣] 1. 概念:数据降维的数学方法 定义 主成分分析(PCA)是一种统计方法,通过正交变 ...

  3. 在webpack中运行vue

    网址:https://vue-loader.vuejs.org/zh/ Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件的格式撰写 Vue 组件 安装loa ...

  4. 一文了解 - -> SpringMVC

    一.SpringMVC概述 Spring MVC 是由Spring官方提供的基于MVC设计理念的web框架. SpringMVC是基于Servlet封装的用于实现MVC控制的框架,实现前端和服务端的交 ...

  5. 何时/如何使用 std::enable_shared_from_this<T>?

    要点回顾 继承自 std::enable_shared_from_this<T> 的类能够在其自身实例中通过 std::shared_from_this 方法创建一个指向自己的 std:: ...

  6. MacOSX 运行Unity卡顿 [gethostname]

    用MacbookPro 32G i7 独显 的高配打开项目发现异常卡顿, Win平台没有问题 打开Unity的Profiler DeepProfiler. 发现完全是卡在 dns.gethostnam ...

  7. C++类与对象详解

    什么是类和对象 类和对象的概念 类是对象的抽象,对象是对客观事物的抽象. 用通俗的话来说: 类是类别的意思,是数据类型. 对象是类别下的具体事物. 也就是说: 类是数据类型,对象是变量. 比如: 水果 ...

  8. Grab 基于 Apache Hudi 实现近乎实时的数据分析

    介绍 在数据处理领域,数据分析师在数据湖上运行其即席查询.数据湖充当分析和生产环境之间的接口,可防止下游查询影响上游数据引入管道.为了确保数据湖中的数据处理效率,选择合适的存储格式至关重要. Vani ...

  9. 文件系统(八):Linux JFFS2文件系统工作原理、优势与局限

    liwen01 2024.06.23 前言 在嵌入式Linux设备中,经常使用jffs2文件系统来作为参数区的文件系统格式.至于为什么要使用jffs2来作为参数区的文件系统,我猜大部分人都没有做过多的 ...

  10. 【Playwright+Python】系列教程(二)手把手带你写一个脚本

    一.如何使用代理方式打开网页 在 playwright.chromium.launch() 中传入 proxy 参数即可,示例代码如下: 1.同步写法: from playwright.sync_ap ...