最近在做一个简单的报表, 用的工具是帆软报表, 一开始觉得有点low, 现在看看还行, 除了界面真的太丑外, 其它还要, 这种大量要使用 sql 的方式, 我觉得是非常灵活高效的, I like . 这个过程 sql 确实也提高了不少. 其中有个需求, 是要做个数据联动, 报表之间的部分字段的联动变化.

需求

两张表, B 表的某些字段要 跟随 A 表的变化实现级联, 也不是级联,就是完全同步.

分析了一波, 本以为要做个级联操作, 但一看, 其实就是, join 就能解决的呀.

实现

首先要考虑 B 表原有的数据不能动, 然后再进行联动.. 还是建表等来说明整个原理吧.

数据准备

drop table if exists tb_01;
create table tb_01(
id varchar(20) primary key,
name varchar(20),
age int,
gender varchar(30), -- 默认值
alive varchar(30) not null default 'alive'
); insert into tb_01(id, name, age, gender) values ('100', 'youge', 24, '男');
insert into tb_01(id, name, age, gender) values ('101', 'xiaojie', 22, '女');
insert into tb_01(id, name, age, gender) values ('102', 'tianer', 22, '女'); drop table if exists tb_02;
create table tb_02(
id varchar(20) primary key, name varchar(20),
age int,
gender varchar(30), dream varchar(20),
city varchar(20),
income int, -- alive 有值表示同步中, 无值则表示离线状态
status varchar(20) null
); insert into tb_02(id) values ('100');
insert into tb_02(id) values ('101');
insert into tb_02(id) values ('102');
insert into tb_02(id) values ('103');

初始数据如下:

-- preview

mysql> select * from tb_01;
+-----+---------+------+--------+
| id | name | age | gender |
+-----+---------+------+--------+
| 100 | youge | 24 | 男 |
| 101 | xiaojie | 22 | 女 |
| 102 | tianer | 22 | 女 |
+-----+---------+------+--------+
3 rows in set (0.00 sec) mysql> select * from tb_02;
+-----+------+------+--------+-------+------+--------+-------+
| id | name | age | gender | dream | city | income | alive |
+-----+------+------+--------+-------+------+--------+-------+
| 100 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 101 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 102 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 103 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+------+------+--------+-------+------+--------+-------+
4 rows in set (0.00 sec)

过程细节

先要让 B 表的数据不能动, 初始化的时候.

select
a.id as a_id, b.id,
b.name,
b.age,
b.gender,
b.dream,
b.city,
b.income,
b.alive from tb_01 as a
right join tb_02 as b
on a.id = b.id

left join 和 right join 灵活使用需要哦

B 表左连接 A 表 这个结果作为 C 表

+------+-----+------+------+--------+-------+------+--------+-------+
| a_id | id | name | age | gender | dream | city | income | alive |
+------+-----+------+------+--------+-------+------+--------+-------+
| 100 | 100 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 101 | 101 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 102 | 102 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| NULL | 103 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+------+-----+------+------+--------+-------+------+--------+-------+

A 表再 和 C 表做左连接 (同步新增等情况的的数据)

select
a.id,
a.name,
a.age,
a.gender, -- c.a_id,
c.dream,
c.city,
c.income,
c.alive from tb_01 as a
left join ( select
a.id as a_id, b.id,
b.name,
b.age,
b.gender,
b.dream,
b.city,
b.income,
b.alive from tb_01 as a
right join tb_02 as b
on a.id = b.id ) as c on a.id = c.id -- A 表删减记录, 不会影响 B 表原有的
and c.a_id is not null
-- 左边作为作为联动标准(中间表01)
+-----+---------+------+--------+-------+------+--------+-------+
| id | name | age | gender | dream | city | income | alive |
+-----+---------+------+--------+-------+------+--------+-------+
| 100 | youge | 24 | 男 | NULL | NULL | NULL | NULL |
| 101 | xiaojie | 22 | 女 | NULL | NULL | NULL | NULL |
| 102 | tianer | 22 | 女 | NULL | NULL | NULL | NULL |
+-----+---------+------+--------+-------+------+--------+-------+
3 rows in set (0.00 sec)

将此中间表01, 主键插入到 目标表 tb_02

主键插入: 主键冲突则覆盖, 否则新增,即在帆软的 主键填报

mysql> select * from tb_02;
+-----+---------+------+--------+-------+------+--------+-------+
| id | name | age | gender | dream | city | income | alive |
+-----+---------+------+--------+-------+------+--------+-------+
| 100 | youge | 24 | 男 | NULL | NULL | NULL | NULL |
| 101 | xiaojie | 22 | 女 | NULL | NULL | NULL | NULL |
| 102 | tianer | 22 | 女 | NULL | NULL | NULL | NULL |
| 103 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+---------+------+--------+-------+------+--------+-------+
4 rows in set (0.00 sec)

等待提交完后, 还要标记出, 哪些是同步的, 哪些是离线的。

即: 用 A 表 right join 目标表, 能匹配上的, 就是同步的呗。

-- step_02 (木丁就是 给 alive 字段打上标签)

select
b.id,
b.name,
b.age,
b.gender,
b.dream,
b.city,
b.income, -- 匹配上的 将 alive 填充为 该记录的ID
a.id as alive from tb_01 as a
right join tb_02 as b
on a.id = b.id
+-----+---------+------+--------+-------+------+--------+-------+-------+
| id | name | age | gender | dream | city | income | alive | alive |
+-----+---------+------+--------+-------+------+--------+-------+-------+
| 100 | youge | 24 | 男 | NULL | NULL | NULL | NULL | 100 |
| 101 | xiaojie | 22 | 女 | NULL | NULL | NULL | NULL | 101 |
| 102 | tianer | 22 | 女 | NULL | NULL | NULL | NULL | 102 |
| 103 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+---------+------+--------+-------+------+--------+-------+-------+
4 rows in set (0.00 sec) => 再 提交一波 (主键插入) 则是最新的了。 mysql> select * from tb_02;
+-----+---------+------+--------+-------+------+--------+-------+
| id | name | age | gender | dream | city | income | alive |
+-----+---------+------+--------+-------+------+--------+-------+
| 100 | youge | 24 | 男 | NULL | NULL | NULL | NULL |
| 101 | xiaojie | 22 | 女 | NULL | NULL | NULL | NULL |
| 102 | tianer | 22 | 女 | NULL | NULL | NULL | NULL |
| 103 | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+---------+------+--------+-------+------+--------+-------+
4 rows in set (0.00 sec)

核心过程

就是两步, 先左连接, 再右连接嘛, 中间需要2次主键插入. 虽然看着这里, sql 很多, 其实主要还是多在字段上, 逻辑非常清晰哦.

select
a.id,
a.name,
a.age,
a.gender, -- c.a_id,
c.dream,
c.city,
c.income,
c.alive from tb_01 as a
left join ( select
a.id as a_id, b.id,
b.name,
b.age,
b.gender,
b.dream,
b.city,
b.income,
b.alive from tb_01 as a
-- 共有的
left join tb_02 as b
on a.id = b.id ) as c on a.id = c.id and c.a_id is not null 提交一波哦 !!! -- step_02 (木丁就是 给 alive 字段打上标签)
select
b.id,
b.name,
b.age,
b.gender,
b.dream,
b.city,
b.income, -- 匹配上的 将 alive 填充为 该记录的ID
a.id as alive from tb_01 as a
right join tb_02 as b
on a.id = b.id

简化版(B表跟A表初始一样)

直接就一个左连接, (主键插入), 然后, 再来一个右连接, 匹配上的 id 给作为 行打上一个标签即可.

-- step_01:
select
a.*,
b.dream,
b.city,
b.income,
b.status from tb_01 as a
left join tb_02 as b
on a.id = b.id
-- step_02:
-- A 表 跟 目标表 右连接, 能匹配上, 就将
-- A表的 id 填到 B 的 alive 字段中.
select
b.id,
b.name,
b.age,
b.gender,
b.dream,
b.city,
b.income,
b.city,
-- A 表的 id (匹配上)
a.alive as status from tb_01 as a
right join tb_02 as b
on a.id = b.id

实现效果

增改查必然是没有问题的的, 主要来看一波删除操作.

现在呢, 假设 A 表将 102 给删掉, 那最终的结果呢, 是在 B 表中, status 的状态 alive 变为 空 而已, 达到 逻辑删除 的效果, 这样也更能满足业务的回查数据的需要.

先一波 102 删除后, 中间表 step_01 的联动效果:

这时候, 目标表, 一旦 刷新 , 这状态就同步了呀.

小结

  • 数据联动 Join 左,右 连接, 就能轻松搞定, 一开始想复杂了, 用主外键级联, 和存储过程, 触发器等复杂方式
  • Join 配合这种 "主键更新表" 的方式, 能实现, 标记字段值的回填, 动态插入值, 这种操作还是很强大的
  • SQL 配合相应的工具使用, 如之前的 Tableau 和现用帆软报表, 越来发现 SQL 是真的香.

Join 实现 2 表数据联动的更多相关文章

  1. 【Spark调优】小表join大表数据倾斜解决方案

    [使用场景] 对RDD使用join类操作,或者是在Spark SQL中使用join语句时,而且join操作中的一个RDD或表的数据量比较小(例如几百MB或者1~2GB),比较适用此方案. [解决方案] ...

  2. mysql left join 右表数据不唯一的情况解决方法

    mysql left join 右表数据不唯一的情况解决方法 <pre>member 表id username1 fdipzone2 terry member_login_log 表id ...

  3. BPM配置故事之案例14-数据字典与数据联动

    小明遇到了点麻烦,他昨天又收到了行政主管发来的邮件,要求把出差申请单改由H3 BPM进行,表单如下 行政主管的出差申请表 小明对表单进行了调整,设计出了一份适合在系统中使用的表单,但在"出差 ...

  4. SQL Server 更改跟踪(Chang Tracking)监控表数据

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...

  5. SQL表关联赋值、系统表、表数据删除

    1. 表与表的关联赋值(用于表与表之间有关联字段,数据互传) 双表关联赋值 UPDATE #B SET #B.D=#A.B from #B inner join #A on #B.C=#A.A 多表关 ...

  6. LINQ 联查多表数据并封装到ViewModel的实现

    LINQ 联查多表数据并封装到ViewModel的实现 public List<MyTask> GetPagedTaskList(int pageIndex, int pageSize, ...

  7. SQL Server 的表数据简单操作(表数据查询)

    --表数据查询----数据的基本查询-- --数据简单的查询--select * | 字段名[,字段名2, ...] from 数据表名 [where 条件表达式] 例: use 商品管理数据库 go ...

  8. 利用Sql实现将指定表数据导入到另一个数据库示例

    因为工作中经常需要将数据从一个数据库导入到另一个数据库中,所以将这个功能写成一个存储过程,以方便调用.现在粘贴出来供大家参考: 注意:1,以下示例中用到了syscolumns,sysobjects等系 ...

  9. SOME:收缩数据库日志文件,查看表数据量和空间占用,查看表结构索引修改时间

    ---收缩数据库日志文件 USE [master]ALTER DATABASE yourdatabasename SET RECOVERY SIMPLE WITH NO_WAITALTER DATAB ...

  10. 工作随笔——mysql子查询删除原表数据

    最近在开发的时候遇到一个mysql的子查询删除原表数据的问题.在网上也看了很多方法,基本也是然并卵(不是写的太乱就是效率太慢). 公司DBA给了一个很好的解决方案,让人耳目一新. DELETE fb. ...

随机推荐

  1. 大模型工具KTransformer的安装

    技术背景 前面写过几篇关于DeepSeek的文章,里面包含了通过Ollama来加载模型,以及通过llama.cpp来量化模型(实际上Llama.cpp也可以用来加载模型,功能类似于Ollama).这里 ...

  2. .NET Core 托管堆内存泄露/CPU异常的常见思路

    常见的思路 内存泄露 托管内存暴涨大多数原因都是因为对象被GC Root(stack,gchandle,finalizequeue)持有,所以一直无法释放,所以观察的重点都在对象的可疑GC Root ...

  3. AI 实践|零成本生成SEO友好的TDK落地方案

    之前写过一篇文章「Google搜索成最大入口,简单谈下个人博客的SEO」,文章里介绍了网页的描述信息TDK(Title.Description和Keywords)对SEO的重要作用,尽管已经意识到了T ...

  4. 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!

    前言 今天大姚给大家分享一款基于 .NET 开源(GPL-2.0 license).免费.功能强大的 Windows 远程连接管理工具,支持 RDP.VNC.SSH 等多种主流协议:mRemoteNG ...

  5. OpenAI的GPT-4o:普通人的AI秘书来了

    1. 惊艳时刻:AI比你想象的更"人性" 早餐时,张三正埋头刷推送,一篇关于OpenAI发布GPT-4o的文章瞬间点燃了他的好奇心.这个AI简直是科技圈的惊雷!竟然可以像真人一样说 ...

  6. 【Java】枚举类和注解

    一.枚举类的使用 1. 枚举类的说明: 枚举类的理解:类的对象只有有限个,确定的.我们称此类为枚举类 当需要定义一组常量时,强烈建议使用枚举类 枚举类的实现: JDK 5.0以前需要自定义 JDK 5 ...

  7. wrk

    github.com/wg/wrk 是一个现代的 HTTP 基准测试工具.

  8. [T.2] 团队项目:选题和需求分析

    项目 内容 这个作业属于哪个课程 2025年春季软件工程(罗杰.任健) 这个作业的要求在哪里 T.2团队项目:选题和需求分析 团队在这个课程的目标是 学习软件工程相关知识,培养编程和团队协作能力,做出 ...

  9. k8s部署dify详细过程

    一.概述 dify官方提供的安装方式是docker-compose方式部署的,单机运行. 但是在企业生产环境,单机没法提供冗余,一旦故障,就很麻烦了. 如果有大量的APP用户,那么单机承受不住这么多并 ...

  10. 基于Lighthouse安装Docker

    1. 前言 在此之前小编通过各种方式介绍过自己通过服务器搭建的一些玩法,也写过一些教程,但是那些教程,现在回头来看,都是有些杂乱了,统一性不强.我就准备重新整理一下之前写的文章,并且准备重新开一个专题 ...