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. python爬虫爬取天气数据并图形化显示

    前言 使用python进行网页数据的爬取现在已经很常见了,而对天气数据的爬取更是入门级的新手操作,很多人学习爬虫都从天气开始,本文便是介绍了从中国天气网爬取天气数据,能够实现输入想要查询的城市,返回该 ...

  2. 如何实现android和服务器长连接

    转载 这种功能实际上就是数据同步,同时要考虑手机本身.电量.网络流量等等限制因素,所以通常在移动端上有一下两个解决方案: 1.一种是定时去server查询数据,通常是使用HTTP协议来访问web服务器 ...

  3. Android-----创建SQLite数据库

    简单介绍一下Android系统内置轻便又功能强大的嵌入式数据库--SQLite. SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎,它是一款轻型的数据库,是遵守ACID的关 ...

  4. CR TubeGet 0.9.2.7,YouTube&全网视频终极下载

    数十次迭代,终于功能完善,在youtube-dl原生支持基础之上,自写解析器脚本,实现对其它主流网站视频下载支持. 加入对视频播放列表.缩略图.字幕下载支持,甚至于自定义列表设计.加密视频下载. 支持 ...

  5. SSH爆破应急响应

    问题发现 登录云主机,根据提示消息,发现正遭受SSH爆破攻击,IP地址为159.65.230.189 查看登录相关安全日志:tail -f /var/log/secure,发现其他尝试爆破IP106. ...

  6. 利用tcpdump抓取网络包

    1.下载并安装tcpdump 下载地址:tcpdump 安装tcpdump,连接adb adb push tcpdump /data/local/tcpdump adb shell chmod 675 ...

  7. kuangbin专题专题四 MPI Maelstrom POJ - 1502

    题目链接:https://vjudge.net/problem/POJ-1502 dijkstra板子题,题目提供下三角情况,不包含正对角线,因为有题意都为0,处理好输入,就是一个很水的题. #inc ...

  8. 版本问题---keras和tensorflow的版本对应关系

    keras和tensorflow的版本对应关系,可参考: Framework Env name (--env parameter) Description Docker Image Packages ...

  9. Fiddler抓websocket协议的包,用jmeter做并发测试

    1.Fiddler: 左边为ws请求url.右边为请求数据,响应数据 jmeter:

  10. Linq入门学习

    千万别被这个页面的滚动条吓到!!! 我相信你一定能在30分钟之内看完它!!! 在说LINQ之前必须先说说几个重要的C#语言特性 一:与LINQ有关的语言特性 1.隐式类型 (1)源起 在隐式类型出现之 ...