分组对列扁平化(列转换行 关系型转换NoSQL)

2023-11-15

前言:

关系型数据库要符合第一范式即原子性,因此字段多值情况只能分行处理,如下表,假设keys是terms、appl_dt,则no, predict_pay_dt, actual_pay_dt 是多值


如果要转换成NoSQL或collection对象,需要以keys分组,然后列转成行(或列转成collection)。

ETL开源工具Kettle也有行扁平化,不过不能分组进行,功能有限。



现以Java实现,示例:

	public static List<Fpd> columnToLine(Connection conn) {
		List<Fpd> fpdList = new ArrayList<Fpd>();
		Fpd preFpd = new Fpd();
		Fpd fpd = new Fpd();
		List<Integer> preAgrList = new ArrayList<Integer>();
		List<Integer> agrList = new ArrayList<Integer>();
		List<Integer> preDefList = new ArrayList<Integer>();
		List<Integer> defList = new ArrayList<Integer>();
		List<Integer> preDefDaysList = new ArrayList<Integer>();
		List<Integer> defDaysList = new ArrayList<Integer>();
		ResultSet rs = selectValue(conn);
		try {
			while(rs.next()){
				
				// 1. copy current line to previous line
				try {
					preFpd = DeepCopy.copy(fpd);
					preAgrList = DeepCopy.copy(agrList);
					preDefList = DeepCopy.copy(defList);
					preDefDaysList = DeepCopy.copy(defDaysList);
				} catch (Exception e) {
					e.printStackTrace();
				}
				
				// 2. assign current line
				fpd = new Fpd();
				fpd.setMobileNo(rs.getString("mobile_no"));
				fpd.setName(rs.getString("name"));
				fpd.setLoanAmount(rs.getInt("loan_amount"));
				fpd.setTerms(rs.getInt("terms"));
				fpd.setApplDt(rs.getString("appl_dt"));
				fpd.setZhangdanNo(rs.getInt("zhangdan_no"));
				agrList.add(rs.getInt("ARG"));
				defList.add(rs.getInt("DEF"));
				defDaysList.add(rs.getInt("DEF_days"));
				
				// 3. if group by keys are different, update record
				if (preFpd.getMobileNo() != null && !fpd.keysEquals(preFpd)) {
					preFpd.setAgr(preAgrList);
					preFpd.setDef(preDefList);
					preFpd.setDefDays(preDefDaysList);
					fpdList.add(preFpd);
					
					agrList.clear();
					defList.clear();
					defDaysList.clear();
					agrList.add(rs.getInt("ARG"));
					defList.add(rs.getInt("DEF"));
					defDaysList.add(rs.getInt("DEF_days"));
				}
			}
			
			// 4. final process (copy current line & update record)
			{
				try {
					preFpd = DeepCopy.copy(fpd);
					preAgrList = DeepCopy.copy(agrList);
					preDefList = DeepCopy.copy(defList);
					preDefDaysList = DeepCopy.copy(defDaysList);
				} catch (Exception e) {
					e.printStackTrace();
				}
				preFpd.setAgr(preAgrList);
				preFpd.setDef(preDefList);
				preFpd.setDefDays(preDefDaysList);
				fpdList.add(preFpd);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return fpdList;
	}


附上转成行后的表批量插入(关系型):

	public static void insertValue(Connection conn, List<Fpd> fpdList) {
	      
	    String sql = "insert into def_analysis ("  
	            + "mobile_no, name, amount, terms, appl_dt, "
	    		+ "AGR_1, AGR_2, AGR_3, AGR_4, AGR_5, AGR_6, "
	    		+ "AGR_7, AGR_8, AGR_9, AGR_10, AGR_11, AGR_12, "
	    		+ "DEF_1, DEF_2, DEF_3, DEF_4, DEF_5, DEF_6, "
	    		+ "DEF_7, DEF_8, DEF_9, DEF_10, DEF_11, DEF_12, "
	    		+ "DEF_DAYS_1, DEF_DAYS_2, DEF_DAYS_3, DEF_DAYS_4, DEF_DAYS_5, DEF_DAYS_6, "
	    		+ "DEF_DAYS_7, DEF_DAYS_8, DEF_DAYS_9, DEF_DAYS_10, DEF_DAYS_11, DEF_DAYS_12"
	            + ") values(?, ?, ?, ?, ?, "
	            + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
	            + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
	            + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?  "
	            + ")";
	    try {  
	        PreparedStatement ps = conn.prepareStatement(sql);  
	        conn.setAutoCommit(false);  
	        for (Fpd fpd:fpdList) {  
	            ps.setString(1,fpd.getMobileNo());  
	            ps.setString(2,fpd.getName());  
	            ps.setInt(3,fpd.getAmount());
	            ps.setInt(4,fpd.getTerms());
	            ps.setString(5,fpd.getApplDt());
	            
	            Iterator<Integer> agrItr = fpd.getAgr().iterator();
	            for(int i = 6; i<18; i++) {
	            	if (agrItr.hasNext())
	            		ps.setInt(i,agrItr.next());
	            	else
	            		ps.setInt(i,0);
	            }
	            Iterator<Integer> defItr = fpd.getDef().iterator();
	            for(int i = 18; i<30; i++) {
	            	if (defItr.hasNext())
	            		ps.setInt(i,defItr.next());
	            	else
	            		ps.setInt(i,0);
	            }
	            Iterator<Integer> defDaysItr = fpd.getDefDays().iterator();
	            for(int i = 30; i<42; i++) {
	            	if (defDaysItr.hasNext())
	            		ps.setInt(i,defDaysItr.next());
	            	else
	            		ps.setInt(i,0);
	            }
	            ps.addBatch();  
	        }
	        ps.executeBatch();  
	        conn.commit();  
	        conn.setAutoCommit(true);  
	       } catch (SQLException e) {  
	        e.printStackTrace();  
	       }  
	}



注意:

previous 对象要用值传递而不能地址传递,DeepCopy可参考:http://blog.csdn.net/textboy/article/details/49075263

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分组对列扁平化(列转换行 关系型转换NoSQL) 的相关文章

随机推荐

  • java深入体会

    javase01阶段 idea几个常用设置 1 调整字体大小 2 自动导包 3 不区分大小写 4 设置背景颜色 小数参与计算 1 小数参与计算才会出现小数 int a 10 int b 20 1 a b 30 1 2 小数参与计算有几率出现
  • Vue echart toolbox 工具栏点击 自定义全屏按钮 显示到弹出框中

    最终效果 说明 由于页面上的echart图表过多 写一个vue子组件 直接在父页面调取复用 安装插件 npm i echarts 在 main js 中引用 import echarts from echarts Vue prototype
  • 读标准03-IEEE1451.5标准协议尝鲜实现

    读标准03 IEEE1451 5标准协议尝鲜实现 前面两个文章里面已经详细描述了 TEDS 和 Message 的组成 这里 C 的实现分两个部分 分别对 TEDS 和 Message 的 数据结构实现 与 帧打包与解析的算法实现 第一版
  • java 程序猿必备技能——Debug详解

    Debug的引入和概述 IDEA中Debug的使用 Debug演示 一 前言 在我们以往的程序执行中 只能看到控制台上展示的最终结果 无法直观清晰地看到程序内部每一个变量的加载 更迭 以及代码执行的内部逻辑 而Debug 断点调试 可以让我
  • python3最新版本-mac下安装Python3.*(最新版本)

    前言 mac系统自带python 不过以当前mac系统的最新版本为例 自带的python版本都是2 版本 虽然不影响老版本项目的运行 但是python最新的3 版本的一些语法与2 版本并不相同 网上的教程大神们也肯定都更新出了最新版的教程
  • VC实现对话框文件拖拽

    使用过QQ的人都知道 只要把文件拖拽到消息框中就可以传送文件了 那么这种功能是如何实现的呢 其实很简单 只需要响应一个WM DROPFILES消息就可以了 在基于对话框的程序中 默认是没有这个消息的 按下Ctrl W 弹出类向导对话框 选择
  • kettle通过java步骤获取汉字首拼

    kettle通过java步骤获取汉字首拼 用途描述 一组数据 需要获取汉字首拼后 输出 实现效果 添加jar包 pinyin4j 2 5 0 jar 自定义常量数据 Java代码 完整代码 import net sourceforge pi
  • 用指针交换两个数

    题目描述 利用指针交换用户输入的两个数 输入 测试次数t 共t行 每行两个整数 输出 共t行 每行输出交换后的两个整数 输入样例1 2 1 2 35 21 输出样例1 2 1 21 35 思路分析 用a和b两个变量把数存储下来 再用两个指针
  • swift4.0自定义UITabBarController +UINavigationController

    首先开始项目之前我们需要搭建框架 首选UITabBarController UINavigationController 下面的代码是整理好的 包括我们会遇到的问题解决方法都在里面 自定义UINavigationController cla
  • TypeScript算法-19. 删除链表的倒数第 N 个结点

    TypeScript算法 19 删除链表的倒数第 N 个结点 思路 代码 思路 要删除倒数第N个节点 就要找到倒数第N 1个节点 然后直接将next指针指向next next即可 为了找到倒数第N 1个节点 可以使用快慢指针 让快指针先走n
  • openGL法线贴图和纹理贴图结合使用,以增强三维物体表面细节

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一 法线贴图 二 代码 1 主程序 2 着色器程序 运行效果 源码下载 前言 凹凸贴图的一种替代方法是使用查找表来替换法向量 这样我们就可以在不依赖数学函 数的情况下 对凸
  • JS复选框:获取选中的checkobx

    div div
  • 异常检测怎么做,试试孤立随机森林算法(附代码)

    点击上方 程序员小乐 关注 星标或置顶一起成长 每天凌晨00点00分 第一时间与你相约 每日英文 If someone hurts you please continue good good to enjoy life hurt the s
  • CentOS7中Docker常规安装Redis

    一 下拉redis docker pull redis 二 处理redis宿主机配置文件相关 mkdir p app redis data mkdir p app redis conf 三 上传一份redis官网默认原始的redis con
  • 超级详细的 Maven 教程(基础+高级)

    1 Maven 是什么 Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供构建和依赖管理支持的工具 一个 Maven 工程有约定的目录结构 约定的目录结构对于 Maven 实现自动化构建而言是必不可少的一环 就
  • PROFIBUS DP从站开发 VPC3源程序分析---user_chk_new_cfg_data(void)

    以下程序注释由成都地质学院霸王猫添加 引用时请尊重作者劳动成果 标明引用者来自成都地质学院霸王猫 UBYTE user chk new cfg data void 入口参数 无 出口参数 无 返回值 VPC3 CFG OK VPC3 CFG
  • SLAM-hector_slam 简介与使用

    hector slam功能包使用高斯牛顿方法 不需要里程计数据 只根据激光信息便可构建地图 所以他的总体框架如下 hector slam功能包 hector slam的核心节点是hector mapping 它订阅 scan 话题以获取SL
  • git-linux-xll?x11-unix 挖矿病毒问题定位与处理

    1 dev服务器出现git用户启动的进程cpu200 的情况 网络传输在高速流量流出 2 首先关停gitlab服务 3 杀死进程后 会马上再出现 无定时任务 4 使用lsof p PID 查看 其中一个名字为 xll unix的文件 该文件
  • put_user

    Linux设备驱动开发笔记 1 复制链接 0 0 skyily 白手起家 帖子 108 主题 105
  • 分组对列扁平化(列转换行 关系型转换NoSQL)

    前言 关系型数据库要符合第一范式即原子性 因此字段多值情况只能分行处理 如下表 假设keys是terms appl dt 则no predict pay dt actual pay dt 是多值 如果要转换成NoSQL或collection