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. sklearn中的KMeans算法

    1.聚类算法又叫做“无监督分类”,其目的是将数据划分成有意义或有用的组(或簇).这种划分可以基于我们的业务需求或建模需求来完成,也可以单纯地帮助我们探索数据的自然结构和分布. 2.KMeans算法将一 ...

  2. windows mysql服务器

    安装完mysql服务器后,需要启动服务器, 才可提供数据库存储服务.windows上如何启动和关闭mysql服务器呢? 1. 启动 进入mysql的安装目录,如D:\Program Files\mys ...

  3. springmvc核心流程

    用户请求DispathcerServlet(前端控制器). (前端控制器)DispatcherServlet接受到请求,将根据请求信息交给处理器映射器(HandlerMapping). 处理器映射器( ...

  4. python基础-os模块

    os 模块 功能:与操作系统交互的模块 使用方式:import os 常用的几种功能 os.path.dirname(文件名) 用于获取当前文件的所在目录 import os # 获取当前文件的所在目 ...

  5. linux防火墙和xshell的链接

    centos7用的firewalld 1.firewalld的基本使用 启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: ...

  6. Nginx + PHP 修改单次请求 最大执行时间

    1.  php.ini  (usr/local/php/etc) max_execution_time = 2. php-fpm.conf  (usr/local/php/etc) request_t ...

  7. 定制你的“魅力”报告--Allure

    “人世间是一个大囚笼,每个人都在狱中,砥砺前行.九狱台中的刺,是生活中所要面对的砥砺,是锋利的刺,将自己肉身刺得千疮百孔,将自己的道心刺得千疮百孔.” ---<牧神记·九狱锁道心> 一.简 ...

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

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

  9. vue项目积累

    (1)--save和--save-dev 安装到开发环境npm axios --save-dev 安装到生产环境npm axios --save .

  10. 第二篇 -- C#中对XML操作

    一.XML文件操作中与.Net中对应的类 微软的.NET框架在System.xml命名空间提供了一系列的类用于Dom的实现. 以下给出XML文档的组成部分对应.NET中的类: XML文档组成部分 对应 ...