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. Android源码分析(四)-----Android源码编译及刷机步骤

    一 : 获取源码: 每个公司服务器地址不同,以如下源码地址为例: http://10.1.14.6/android/Qualcomm/msm89xx/branches/msm89xx svn环境执行: ...

  2. Python 栈、队列的实现

    在python中,列表既可以作为栈使用,又可以作为队列使用. 把列表作为栈使用 栈:后进先出 stack=[1,2,3] stack.append(4) #入栈,以列表尾部为栈顶 print(stac ...

  3. 使用DocumentFormat.OpenXml操作Excel文件.xlsx

    1.开始 DocumentFormat.OpenXml是ms官方给一个操作office三大件新版文件格式(.xlsx,.docx,.pptx)的组件:特色是它定义了OpenXml所包含的所有对象(たぶ ...

  4. SpringBoot2.x的Maven依赖配置

    本篇主要说明以下内容: 1.SpringBoot2.x中Maven的配置内容,即:pom.xml的内容说明 1 Maven依赖的配置方式 使用Maven来配置SpringBoot2.x,有两种方式: ...

  5. etcd和flannel实现docker跨物理机通信

    实验目标 跨物理机的容器之间能直接访问docker通过Flannel可以实现各容器间的相互通信,即宿主机和容器,容器和容器之间都能相互通信 实验环境 192.168.3.50 //etcd.flann ...

  6. Shell 编程 条件语句

    本篇主要写一些shell脚本条件语句的使用. 条件测试 test 条件表达式 [ 条件表达式 ] 文件测试 -d:测试是否为目录(Directory). -e:测试文件或目录是否存在(Exist). ...

  7. 阿里云ECS-使用putty产品psftp工具上传下载

    本人windows10,安装了winscp3,原本可以简单易用,但天空不作美,死活不让我连接,无奈,只能换命令行方式, 好在,putty提供了一个小工具,psftp,不过,需要去官网下载完整版才有哦, ...

  8. 性能测试基础---LR参数化相关

    性能测试脚本的增强:·参数化·关联·事务·检查点·思考时间·集合点 ·参数化:模拟不同用户的不同请求. ·为什么要做参数化? ·功能:通常来说,系统的某些业务数据具有唯一性的要求. ·性能:一般来说, ...

  9. mocker-api 原理

    项目网址:https://github.com/jaywcjlove/mocker-api 作用有2个: 运行dev命令后,访问本地开启服务接口,模拟数据: 访问本机接口时,代理到其它服务器,即调用其 ...

  10. 31、Python程序中的协程操作(greenlet\gevent模块)

    一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是协程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 对比操作系统控制线程的切换,用 ...