一条sql让你学会java中的lambda

一条sql让你学会java中的lambda

引:

关于lambda表达式看了很多博客,也看了相关视频,看的时候感觉都会,实操还是出了问题,最近写了一条复杂sql,想着用lambda实现相同效果,前前后后花了不少时间,总算搞懂了lambda的基本使用,废话少说,一起来看看。

题目:

涉及数据库表:人员表NMG. Emp_Info

字段名称类型说明
Education文本学历
Department_Code关联关联病区编码
Enabled文本状态(0禁用1启用)
JoinTime时间类型入职时间

病区表dbo. MD_Ward

字段名称类型说明
code文本病区编码
Name文本病区名称
ID文本病区ID

要求:

查询所有病区下的人员根据入职时间分成 1年以内,1-2年以内,3-4以内,5-10以内,10-20以内,>20年 六个阶段的人员数量

筛选条件:

人员状态=1
病区ID !=72 and ID!=79 and ID!=236

mysql实现

代码

SELECT W.Name AS 病区,
COUNT(*) AS 人员数量,
       SUM(CASE WHEN DATEDIFF(YEAR, E.JoinTime, GETDATE()) < 1 THEN 1 ELSE 0 END) AS 一年以内,
       SUM(CASE WHEN DATEDIFF(YEAR, E.JoinTime, GETDATE()) BETWEEN 1 AND 2 THEN 1 ELSE 0 END) AS 一到二年以内,
       SUM(CASE WHEN DATEDIFF(YEAR, E.JoinTime, GETDATE()) BETWEEN 3 AND 4 THEN 1 ELSE 0 END) AS 三到四年以内,
       SUM(CASE WHEN DATEDIFF(YEAR, E.JoinTime, GETDATE()) BETWEEN 5 AND 10 THEN 1 ELSE 0 END) AS 五到十年以内,
       SUM(CASE WHEN DATEDIFF(YEAR, E.JoinTime, GETDATE()) BETWEEN 10 AND 20 THEN 1 ELSE 0 END) AS 十到二十年以内,
       SUM(CASE WHEN DATEDIFF(YEAR, E.JoinTime, GETDATE()) > 20 THEN 1 ELSE 0 END) AS 大于20FROM NMG.Emp_Info AS E
JOIN dbo.MD_Ward AS W ON E.Department_Code = W.code
WHERE E.Enabled = '1'
  AND W.ID NOT IN (72, 79, 236)
GROUP BY W.Name;

执行结果

统计一下人员总数,方便后面对照结果(总数276)

lambda实现

ok,做完这些现在用lambda实现一下,因为lambda不好做连接查询(chatgpt生成出来使用lambda实现连接看不懂)我们就用mysql做连接查询

执行sql

SELECT
	dbo.MD_Ward.code,
	dbo.MD_Ward.Name,
	dbo.MD_Ward.ID,
	NMG.Emp_Info.Education,
	NMG.Emp_Info.Enabled,
	NMG.Emp_Info.JoinTime 
FROM
	dbo.MD_Ward
	LEFT JOIN NMG.Emp_Info ON NMG.Emp_Info.Department_Code = dbo.MD_Ward.code

结果

过滤(filter)

allList的数据

过滤掉id=72(其他过滤条件大同小异)

分组(终结方法中的Collectors.groupingBy)

按照病区进行分组

代码实现

Map<String, List<All>> collect = allList.stream()
                    .filter(list -> "1".equals(list.getEnabled()))
                    .filter(list -> !StringUtils.isEmpty(list.getJoinTime()))
                    .filter(list -> !StringUtils.isEmpty(list.getName()))
                    .filter(list -> !Arrays.asList("72", "79", "236").contains(list.getiD()))
                    .collect(Collectors.groupingBy(All::getName));

collect中的数据

现在最简单的过滤做完了,那么接下来需要按照JionTime对人员进行分组,一种是将collect集合循环,拿到每一个时间与当前时间相减,算出年限。另一种是lambda实现,我两种都写一下。

循环实现:

 Map<String, Object> kmap = new HashMap<>();
            collect.forEach((k, v) -> {
                Map<String, List<All>> vmap = new HashMap<>();
                vmap.put("1年以内", new ArrayList<>());
                vmap.put("1-2年以内", new ArrayList<>());
                vmap.put("3-4以内", new ArrayList<>());
                vmap.put("5-10以内", new ArrayList<>());
                vmap.put("10-20以内", new ArrayList<>());
                vmap.put(">20年", new ArrayList<>());
                for (All all : v) {
                    if (StringUtils.isEmpty(all.getJoinTime())) {
                        break;
                    }
                    LocalDate localDate =
                            NbUtil.getDt(all.getJoinTime()).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    long years = ChronoUnit.YEARS.between(localDate, LocalDate.now());

                    if (years < 1) {
                        List<All> allList1 = vmap.get("1年以内");
                        allList1.add(all);
                    } else if (years >= 1 && years <= 2) {
                        List<All> allList1 = vmap.get("1-2年以内");
                        allList1.add(all);
                    } else if (years >= 3 && years <= 4) {
                        List<All> allList1 = vmap.get("3-4以内");
                        allList1.add(all);
                    } else if (years >= 5 && years <= 10) {
                        List<All> allList1 = vmap.get("5-10以内");
                        allList1.add(all);
                    } else if (years >= 10 && years <= 20) {
                        List<All> allList1 = vmap.get("10-20以内");
                        allList1.add(all);
                    } else {
                        List<All> allList1 = vmap.get(">20年");
                        allList1.add(all);
                    }
                }

                kmap.put(k, vmap);
            });

            System.out.println(kmap);

得到的kmap

lambda实现

在写代码之前,先思考一下如果是你,你会怎么写这段lambda代码呢?

将一下我的思路,先统计每个病区的年限,得到一个年限数字字符串,在对年限进行统计。

终结操作(reduce)map reduce

不会不懂reduce看一节 三根reduce(一)就够了

通过map拿到日期数据

reduce处理拿到年限,并且进行拼接

代码

Map<String, String> map = new HashMap<>();
            collect.forEach((k, v) -> {
                String reduce = v.stream()
                        .map(list -> list.getJoinTime())
                        .reduce("", (初始值, joinTime) -> {
                            LocalDate localDate = NbUtil.getDt(joinTime).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                            return 初始值 + "," + String.valueOf(ChronoUnit.YEARS.between(localDate, LocalDate.now()));
                        });
                System.out.println(k + "," + reduce + ":" + (reduce.split(",").length - 1));
                map.put(k, reduce);
            });

结果

这时候差不多就结束了,拿到字符串split(“,”)一下,在对集合循环处理一下就好(其他办法没想出来)

如果我写lambda上瘾了想用lambda处理怎么办?可以这样实现。

代码

map.forEach((k, v) -> {
                List<Map<String, Integer>> mapList = new ArrayList<>();
                Map<String, Integer> mapp = new HashMap<>();

                Integer year1 = Arrays.stream(v.split(","))
                        .filter(list -> !StringUtils.isEmpty(list))
                        .map(list -> Integer.valueOf(list))
                        .reduce(0, (identity, year) -> {
                            if (year < 1) {
                                return identity + 1;
                            } else {
                                return identity;
                            }
                        });
                mapp.put("一年以内", year1);

                Integer year2 = Arrays.stream(v.split(","))
                        .filter(list -> !StringUtils.isEmpty(list))
                        .map(list -> Integer.valueOf(list))
                        .reduce(0, (identity, year) -> {
                            if (year >= 1 && year <= 2) {
                                return identity + 1;
                            } else {
                                return identity;
                            }
                        });
                mapp.put("一到二年以内", year2);
}                

多余的就不写了,可以看出来 还是比较麻烦的,不如循环。

验证

统计一下总数

代码

            final int[] count = new int[1];
            System.out.println("count:" + count[0]);
            result.forEach((k, v) -> {
                for (Map<String, Integer> stringIntegerMap : v) {
                    stringIntegerMap.forEach((key, value) -> {
                        count[0] = count[0] + value;
                        System.out.println(k + "," + key + ":" + value);
                    });
                }
            });
            System.out.println("count:" + count[0]);

结果

在这里插入图片描述

276,与mysql执行的一样,数据我也对过,没问题。

总结

lambda方法有很多,我只讲了与我这段sql相关的,其他用到的时候看一下就OK了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值