package com.ufo.leftjoin;

import java.security.MessageDigest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;

// Used for JDBC connection to DB
class DBParam {
    public static final String Driver = "oracle.jdbc.driver.OracleDriver";
    public static final String DbUrl = "。。。。。。。。MSAPDB";
    public static final String User = "R。。。。。。。A_USER";
    public static final String Pswd = "FF。。。。。。。。wCP";
}

// Used for collection sort
class KeyValue implements Comparable<KeyValue> {
    String key;
    Object value;

    @Override
    public int compareTo(KeyValue another) {
        return this.key.compareTo(another.key);
    }
}

// Used for hold columns
class DhItem{
    String order_no;
    String shipper_code;
    String vehicle_name;
    String vehicle_code;
    String reason_name_mobile;
    String status_name_mobile;

    public String toString() {
        List<String> ls=new ArrayList<String>();

        ls.add(order_no);
        ls.add(shipper_code);
        ls.add(vehicle_name);
        ls.add(vehicle_code);
        ls.add(reason_name_mobile);
        ls.add(status_name_mobile);

        return String.join(",", ls);
    }
}

// Left jion/inner join comparison
public class SqlComparison {
    private static Logger log = Logger.getLogger(SqlComparison.class);

    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;

        try {
            Class.forName(DBParam.Driver).newInstance();
            Properties pro = new Properties();
            pro.setProperty("user", DBParam.User);// 这里不是username或是usr!
            pro.setProperty("password", DBParam.Pswd);// 这里不是pswd
            // pro.setProperty("initialSize", "10");
            // pro.setProperty("maxActive", "12");
            // pro.put("remarksReporting","true");// 这一句才能让rs.getString("REMARKS")起作用

            conn = DriverManager.getConnection(DBParam.DbUrl, pro);
            stmt = conn.createStatement();

            SqlComparison sc = new SqlComparison();

            sc.queryTotalCntinDH(stmt);
            sc.testLeftJoin(stmt);
            sc.testInnerJoin(stmt);

            sc.compareTwoPlan(stmt);
        } catch (Exception e) {
            System.out.print(e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                stmt.close();
                conn.close();
            } catch (SQLException e) {
                log.error("Can't close stmt/conn because of " + e.getMessage());
            }
        }
    }

    /**
     * Compare left to inner
     * @param stmt
     * @throws SQLException
     */
    private void compareTwoPlan(Statement stmt) throws SQLException {
        long startMs = System.currentTimeMillis();

        String leftSql=getLeftjoinSql();
        Map<String,DhItem> leftMap=new HashMap<String,DhItem>();

        ResultSet rs = stmt.executeQuery(leftSql);
        while (rs.next()) {
            DhItem dhItem=new DhItem();
            dhItem.order_no=rs.getString("order_no");
            dhItem.shipper_code=rs.getString("shipper_code");
            dhItem.vehicle_name=rs.getString("vehicle_name");
            dhItem.vehicle_code=rs.getString("vehicle_code");
            dhItem.reason_name_mobile=rs.getString("reason_name_mobile");
            dhItem.status_name_mobile=rs.getString("status_name_mobile");
            leftMap.put(toMD5(dhItem.toString()), dhItem);
        }

        String innerSql=getNewInnerSql();
        Map<String,DhItem> innerMap=new HashMap<String,DhItem>();

        rs = stmt.executeQuery(innerSql);
        while (rs.next()) {
            DhItem dhItem=new DhItem();
            dhItem.order_no=rs.getString("order_no");
            dhItem.shipper_code=rs.getString("shipper_code");
            dhItem.vehicle_name=rs.getString("vehicle_name");
            dhItem.vehicle_code=rs.getString("vehicle_code");
            dhItem.reason_name_mobile=rs.getString("reason_name_mobile");
            dhItem.status_name_mobile=rs.getString("status_name_mobile");
            innerMap.put(toMD5(dhItem.toString()), dhItem);
        }

        List<DhItem> onlyInLeftLs=new ArrayList<DhItem>();
        int count=0;
        for(String key:leftMap.keySet()) {
            if(innerMap.containsKey(key)) {
                count++;
            }else {
                DhItem dhItem=leftMap.get(key);
                onlyInLeftLs.add(dhItem);
            }
        }

        log.info("There are "+toEastNumFormat(count)+" records in both left and inner.");
        log.info("There are "+toEastNumFormat(onlyInLeftLs.size())+" records only in left.");

        List<DhItem> onlyInInnerLs=new ArrayList<DhItem>();

        count=0;
        for(String key:innerMap.keySet()) {
            if(leftMap.containsKey(key)) {
                count++;
            }else {
                DhItem dhItem=innerMap.get(key);
                onlyInInnerLs.add(dhItem);
            }
        }

        log.info("There are "+toEastNumFormat(count)+" records in both left and inner.");
        log.info("There are "+toEastNumFormat(onlyInInnerLs.size())+" records only in inner.");

        long endMs = System.currentTimeMillis();
        log.info("It takes "+ms2DHMS(startMs,endMs)+" to run function:'compareTwoPlan'.");
    }

    private String getLeftjoinSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("     SELECT                                              ");
        sb.append("      DH1.ORDER_NO,                                   ");
        sb.append("      DH1.SHIPPER_CODE ,                              ");
        sb.append("      DH1.VEHICLE_NAME,                               ");
        sb.append("      DH1.VEHICLE_CODE ,                              ");
        sb.append("      DH1.REASON_NAME_MOBILE,                         ");
        sb.append("      DH1.STATUS_NAME_MOBILE                          ");
        sb.append("  from                                                ");
        sb.append("      DELIVERY_HISTORY DH1                            ");
        sb.append("      left JOIN DELIVERY_HISTORY DH2 on               ");
        sb.append("      DH1.SHIPPER_CODE = DH2.SHIPPER_CODE             ");
        sb.append("      and DH1.ORDER_NO = DH2.ORDER_NO                 ");
        sb.append("      and DH2.UPDATED_DATETIME > DH1.UPDATED_DATETIME ");
        sb.append("  where DH2.UPDATED_DATETIME IS NULL                  ");
        sb.append("      and DH1.DISABLED_FLG = 0                        ");
        String sql = sb.toString();
        return sql;
    }

    private String getInnerSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("    select   ");
        sb.append("      DH1.ORDER_NO,                                   ");
        sb.append("      DH1.SHIPPER_CODE ,                              ");
        sb.append("      DH1.VEHICLE_NAME,                               ");
        sb.append("      DH1.VEHICLE_CODE ,                              ");
        sb.append("      DH1.REASON_NAME_MOBILE,                         ");
        sb.append("      DH1.STATUS_NAME_MOBILE                          ");
        sb.append("  from                                                                                      ");
        sb.append("         DELIVERY_HISTORY dh1 ,                                                                ");
        sb.append("         (select SHIPPER_CODE,ORDER_NO,max(UPDATED_DATETIME) as utime  from DELIVERY_HISTORY   ");
        sb.append("             group by SHIPPER_CODE,ORDER_NO) dh2                                               ");
        sb.append("     where                                                                                     ");
        sb.append("         dh1.SHIPPER_CODE=dh2.SHIPPER_CODE and                                                 ");
        sb.append("         dh1.ORDER_NO=dh2.ORDER_NO and                                                         ");
        sb.append("         dh1.UPDATED_DATETIME=dh2.utime and                                                    ");
        sb.append("         dh1.DISABLED_FLG='0'                                                                  ");

        String sql = sb.toString();

        return sql;
    }

    private String getNewInnerSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("    select ");
        sb.append("          a.ORDER_NO,         ");
        sb.append("          a.SHIPPER_CODE ,     ");
        sb.append("          a.VEHICLE_NAME,          ");
        sb.append("          a.VEHICLE_CODE ,             ");
        sb.append("          a.REASON_NAME_MOBILE,         ");
        sb.append("          a.STATUS_NAME_MOBILE ,");
        sb.append("          a.UPDATED_DATETIME");
        sb.append("    from DELIVERY_HISTORY a");
        sb.append("    where not exists(select 1 ");
        sb.append("    from DELIVERY_HISTORY b");
        sb.append("    where b.SHIPPER_CODE=a.SHIPPER_CODE and b.ORDER_NO=a.ORDER_NO and b.UPDATED_DATETIME>a.UPDATED_DATETIME)");
        sb.append("         and  a.DISABLED_FLG=0                                                                  ");

        String sql = sb.toString();
        return sql;
    }

    // test leftjoin plan
    private boolean testLeftJoin(Statement stmt)  throws SQLException {
        StringBuilder sb = new StringBuilder();
        sb.append("     SELECT                                              ");
        sb.append("      DH1.ORDER_NO,                                   ");
        sb.append("      DH1.SHIPPER_CODE                               ");
        sb.append("  from                                                ");
        sb.append("      DELIVERY_HISTORY DH1                            ");
        sb.append("      left JOIN DELIVERY_HISTORY DH2 on               ");
        sb.append("      DH1.SHIPPER_CODE = DH2.SHIPPER_CODE             ");
        sb.append("      and DH1.ORDER_NO = DH2.ORDER_NO                 ");
        sb.append("      and DH2.UPDATED_DATETIME > DH1.UPDATED_DATETIME  ");
        sb.append("  where DH2.UPDATED_DATETIME IS NULL                  ");
        sb.append("      and DH1.DISABLED_FLG = 0                        ");
        String sql = sb.toString();

        long startMs = System.currentTimeMillis();
        stmt.executeQuery(sql);
        long endMs = System.currentTimeMillis();
        log.info("It takes "+ms2DHMS(startMs,endMs)+" to run leftjoin plan.");

        log.info("Got " + toEastNumFormat(evaluateCntinSql(sql,stmt)) + " records after running leftjoin.");
        return true;
    }

    // test innerjoin plan
    private boolean testInnerJoin(Statement stmt)  throws SQLException {
        StringBuilder sb = new StringBuilder();
        sb.append("    select ");
        sb.append("          a.ORDER_NO,         ");
        sb.append("          a.SHIPPER_CODE      ");
        //sb.append("          a.VEHICLE_NAME,          ");
        //sb.append("          a.VEHICLE_CODE ,             ");
        //sb.append("          a.REASON_NAME_MOBILE,         ");
        //sb.append("          a.STATUS_NAME_MOBILE ,");
        //sb.append("          a.UPDATED_DATETIME");
        sb.append("    from DELIVERY_HISTORY a");
        sb.append("    where not exists(select 1 ");
        sb.append("    from DELIVERY_HISTORY b");
        sb.append("    where b.SHIPPER_CODE=a.SHIPPER_CODE and b.ORDER_NO=a.ORDER_NO and b.UPDATED_DATETIME>a.UPDATED_DATETIME)");
        sb.append("         and  a.DISABLED_FLG=0                                                                  ");

        String sql = sb.toString();

        long startMs = System.currentTimeMillis();
        stmt.executeQuery(sql);
        long endMs = System.currentTimeMillis();
        log.info("It takes "+ms2DHMS(startMs,endMs)+" to run inner join plan.");

        log.info("Got " + toEastNumFormat(evaluateCntinSql(sql,stmt)) + " records after running inner join.");
        return true;
    }

    // evaluate how many records int resultset after running a sql
    private long evaluateCntinSql(String sql,Statement stmt) throws SQLException {
        String sql2 = "select count(*) as cnt from ("+sql+") ";

        ResultSet rs = stmt.executeQuery(sql2);
        while (rs.next()) {
            int cnt = rs.getInt("cnt");
            return cnt;
        }
        return 0;
    }

    // query how many records in table delivery_history
    private boolean queryTotalCntinDH(Statement stmt) throws SQLException {
        String sql = "select count(*) as cnt from delivery_history";

        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
            int cnt = rs.getInt("cnt");
            log.info("There are " + toEastNumFormat(cnt) + " records in the table:'delivery_history'.");
        }
        return true;
    }

    // 将整数在万分位以逗号分隔表示
    public static String toEastNumFormat(long number) {
        DecimalFormat df = new DecimalFormat("#,####");
        return df.format(number);
    }

    /**
     * change seconds to DayHourMinuteSecond format
     *
     * @param startMs
     * @param endMs
     * @return
     */
    private static String ms2DHMS(long startMs, long endMs) {
        String retval = null;
        long secondCount = (endMs - startMs) / 1000;
        String ms = (endMs - startMs) % 1000 + "ms";

        long days = secondCount / (60 * 60 * 24);
        long hours = (secondCount % (60 * 60 * 24)) / (60 * 60);
        long minutes = (secondCount % (60 * 60)) / 60;
        long seconds = secondCount % 60;

        if (days > 0) {
            retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
        } else if (hours > 0) {
            retval = hours + "h" + minutes + "m" + seconds + "s";
        } else if (minutes > 0) {
            retval = minutes + "m" + seconds + "s";
        } else {
            retval = seconds + "s";
        }

        return retval + ms;
    }

    public static String toMD5(String key) {
        char hexDigits[] = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        try {
            byte[] btInput = key.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

}

--END-- 2019-12-20 18:26

SqlComparison的更多相关文章

  1. 2. MongoDB基本操作 —— 用Mongo.exe操作数据库增删改查

    一.开篇 传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成,MongoDB是由数据库(database).集合(collection).文档对象 ...

  2. CentOS MongoDB 高可用实战

    原文:https://www.sunjianhua.cn/archives/centos-mongodb.html 一.MongoDB 单节点 1.1.Windows 版安装 1.1.1 获取社区版本 ...

  3. 170504、MongoDB和MySQL对比(译)

    一.概要 几十年来,关系型数据库已经成为企业应用程序的基础,自从MySQL在1995年发布以来,它已经成为一种受欢迎并且廉价的选择.然而随着近年来数据量和数据的不断激增,非关系数据库技术如MongoD ...

  4. urlx

    2015-09-24 23:41:26 centos6.6下安装MongoDB3.0.1 https://www.percona.com/doc/percona-tokumx/installation ...

  5. Node.js 操作Mongodb

    Node.js 操作Mongodb1.简介官网英文文档  https://docs.mongodb.com/manual/  这里几乎什么都有了MongoDB is open-source docum ...

  6. SQL to MongoDB Mapping Chart

    http://docs.mongodb.org/manual/reference/sql-comparison/ In addition to the charts that follow, you ...

  7. MongoDB 走马观花(全面解读篇)

    目录 一.简介 二.基本模型 BSON 数据类型 分布式ID 三.操作语法 四.索引 索引特性 索引分类 索引评估.调优 五.集群 分片机制 副本集 六.事务与一致性 一致性 小结 一.简介 Mong ...

  8. 了解 MongoDB 看这一篇就够了【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  9. 了解 MongoDB 看这一篇就够了【华为云分享】

    目录 一.简介 二.基本模型 BSON 数据类型 分布式ID 三.操作语法 四.索引 索引特性 索引分类 索引评估.调优 五.集群 分片机制 副本集 六.事务与一致性 一致性 小结 一.简介 Mong ...

随机推荐

  1. 英语SouthRedAgate南红玛瑙

    南红玛瑙(SouthRedAgate)是玛瑙的一个种类,古称”赤玉”,质地细腻油润,是中国独有的品种.由于产量稀少,老南红玛瑙价格急剧上升.南红玛瑙曾被古人用之入药,养心养血. 现在的南红玛瑙已经和和 ...

  2. Android编译系统中的Android.bp

    https://www.cnblogs.com/bluestorm/p/10895005.html Android.bp,是用来替换Android.mk的配置文件. 它使用Blueprint框架来解析 ...

  3. 数据结构与算法5—KMP算法

    串的模式匹配算法 子串(模式串)的定位操作通常称为串的模式匹配. 这是串的一种重要操作,很多 软件,若有“编辑”菜单项的话, 则其中必有“查找”子菜单项. 串的顺序存储实现 #include<s ...

  4. Echarts实现Excel趋势线和R平方计算思路

    测试数据 [19550, 7.1 ],[22498, 8.44 ],[25675, 9.56 ],[27701, 10.77],[29747, 11.5 ],[32800, 12.27],[34822 ...

  5. angular8 打包时 文件过大 导致内存溢出解决方案(记录)

    在package.json 中添加 "scripts": { "ng": "ng", "start": "ng ...

  6. go test benchmark

    Benchtest的简单使用 一个简单的benchtest用例 // 以BenchmarkXXX类似命名,并传入b *testing.B 参数 func BenchmarkLoopSum(b *tes ...

  7. JavaFX 学生登陆表格

    利用JavaFX实现一个学生登陆的界面,其中包括各种JavaFX组件的使用,利用焦点变动自动检测内容的合法性和监控文本输入以及页面的跳转,具体代码如下: /* * To change this lic ...

  8. jmeter压测学习2-linux运行jmeter环境

    前言 使用jmeter做压测的时候,在windows上不太稳定,所有一直在linux服务器上使用jmeter做压力测试. 本篇记录下linux上搭建jmeter环境,以及运行jmeter脚本,查看报告 ...

  9. 第三方百度网盘客户端 PanDownload、速盘、panlight

    PanDownload PanDownload是一款能够快速下载百度网盘内资源的强大工具.PanDownload能够无限速高速下载,满速下载百度云盘里的各种资源.而且PanDownload完全免费,免 ...

  10. 去除WordPress分类描述P标签

    我们知道栏目页调用栏目描述直接用<?php echo category_description(); ?>就ok了,但是使用上面的代码调用Wordpress分类描述,会自动出现P标签,如& ...