发票连号判断-两种实现方式

两种方式找出连号发票

1. 需求

在做票据夹功能的时候,有一个功能叫查找这个单据中所有连号的发票。换个角度说是:给定一个自然数集合,求这个自然数集合中包含多少个自然数串。这么想就简单了,可以使用两种方法实现:
方法1 : 使用sql, 一条sql语句查询出所有连号的发票,本人使用的是mysql8+;
方法2: 使用java,也就是把所有的发票号码查出来,通过写java代码来实现这个功能;
方法3: 使用js ,其实跟java一样,就不再写了;

众所周知:发票连号只判断增值税票和出租车票,下面的我就不再写条件了

2. 方法1 SQL

SELECT
	grp AS diff,
	COUNT(*) AS countNum,
	GROUP_CONCAT( INVOICE_CODE ORDER BY INVOICE_CODE ) AS invoiceCodes,
	INVOICE_TYPE AS invoiceType 
FROM
	( SELECT INVOICE_CODE, INVOICE_CODE - ROW_NUMBER() OVER ( ORDER BY INVOICE_CODE ) AS grp, INVOICE_TYPE FROM pbs_invoice_ocr pio ) cte 
WHERE
	grp IS NOT NULL 
GROUP BY
	grp 
HAVING
	COUNT(*) > 1

解析:
这里使用到了开窗函数,如果不了解的话,可以自行百度下,
ROW_NUMBER():是行号,从1开始计数
INVOICE_CODE:发票号
INVOICE_TYPE:发票类型‘
子查询 cte:
SELECT INVOICE_CODE, INVOICE_CODE - ROW_NUMBER() OVER ( ORDER BY INVOICE_CODE ) AS grp, INVOICE_TYPE FROM pbs_invoice_ocr pio ) cte
这句话的意思是:

  • ROW_NUMBER() OVER ( ORDER BY INVOICE_CODE ):根据 INVOICE_CODE
    对记录进行排序,并为每个记录分配一个唯一的行号。

  • INVOICE_CODE - ROW_NUMBER():计算每个记录的 INVOICE_CODE 减去行号,作为分组依据。
    grp:用于分组的字段。

例如: 发票号是:1 2 5 9 10
行号是:1 2 3 4 5
相减的结果是:0,0,2,5,5
结果显而易见: 1 2 9 10 是连号的发票

外部查询
相对就简单了 :

  • HAVING COUNT(*) > 1:只保留分组记录数大于 1 的结果。
  • GROUP BY grp:按 grp 分组。

3. 方法2 JAVA

这个就是纯算法了, debug 下就能看懂

/**
     * 查找连续的自然数
     *
     * @param invoiceCodeList
     * @return
     */
    private List<List<String>> getConsecutiveNumberList(List<String> invoiceCodeList) {
        // 判断是否连号
        //收集的总的连续列表
        List<List<String>> resultCon = new ArrayList<>();
        //每个收集的连续临时列表
        List<String> tempList = new ArrayList<>();
        for (int i = 0; i < invoiceCodeList.size(); i++) {
            String current = invoiceCodeList.get(i);
            if (!isOnlyDigits(current.trim())) {
                continue;
            }
            BigDecimal currentNum = new BigDecimal(current);
            if (i < invoiceCodeList.size() - 1) {
                String next = invoiceCodeList.get(i + 1);
                if (!isOnlyDigits(next.trim())) {
                    continue;
                }
                BigDecimal nextNum = new BigDecimal(next);
                if (nextNum.subtract(currentNum).compareTo(BigDecimal.ONE) == 0) {
                    // 连续
                    tempList.add(current);
                } else {
                    // 不连续
                    // 不连续时,把最后一个数放进去之前的临时列表
                    tempList.add(current);
                    resultCon.add(tempList);
                    //同时把临时列表置空
                    tempList = new ArrayList<>();
                }
            } else {
                //最后一个元素时,放入最后一个临时列表中
                tempList.add(current);
                resultCon.add(tempList);
            }
        }
        return resultCon;
    }

使用BigDecimal 是因为能算大数

若有错误,希望大佬指出。
对你有帮助给点个👍再走呗。

您可以使用以下代码实现出租车连号校验: ```java import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); int[] number = new int[N]; for (int i = 0; i < N; i++) { number[i = in.nextInt(); } int result = 0; for (int i = 0; i < N; i++) { int max = number[i]; int min = number[i]; for (int j = i; j < N; j++) { max = Math.max(max, number[j]); min = Math.min(min, number[j]); if (max - min == j - i) { result++; } } } System.out.println(result); } } ``` 这段代码会先读取输入的出租车号码数量N,然后读取N个出租车号码,并对号码进行连号校验。最后输出符合条件的连号数量。请注意,该代码是使用简单的循环来实现连号校验的,没有使用jdk1.6及以上版本的特性。123 #### 引用[.reference_title] - *1* [java实现第四届蓝桥杯连号区间数](https://blog.csdn.net/a1439775520/article/details/97654467)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] - *2* [Java实现 蓝桥杯 历届试题 连号区间数](https://blog.csdn.net/a1439775520/article/details/97425988)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] - *3* [Java习题练习:连号区间数](https://blog.csdn.net/m0_51456787/article/details/123580836)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值