Commit 705a3e53cae4df60995c9e27274bcdf6e5a7607d

Authored by scholar
1 parent d556b292

CRM员工业绩统计PR v2.0

yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPerformanceController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
  6 +import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsPerformanceService;
  7 +import io.swagger.v3.oas.annotations.Operation;
  8 +import io.swagger.v3.oas.annotations.tags.Tag;
  9 +import org.springframework.security.access.prepost.PreAuthorize;
  10 +import org.springframework.validation.annotation.Validated;
  11 +import org.springframework.web.bind.annotation.GetMapping;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RestController;
  14 +
  15 +import jakarta.annotation.Resource;
  16 +import jakarta.validation.Valid;
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +
  21 +
  22 +@Tag(name = "管理后台 - CRM 员工业绩统计")
  23 +@RestController
  24 +@RequestMapping("/crm/statistics-performance")
  25 +@Validated
  26 +public class CrmStatisticsPerformanceController {
  27 +
  28 + @Resource
  29 + private CrmStatisticsPerformanceService performanceService;
  30 +
  31 + @GetMapping("/get-contract-count-performance")
  32 + @Operation(summary = "员工业绩-签约合同数量")
  33 + @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
  34 + public CommonResult<List<CrmStatisticsPerformanceRespVO>> getContractCountPerformance(@Valid CrmStatisticsPerformanceReqVO performanceReqVO) {
  35 + return success(performanceService.getContractCountPerformance(performanceReqVO));
  36 + }
  37 +
  38 + @GetMapping("/get-contract-price-performance")
  39 + @Operation(summary = "员工业绩-获得合同金额")
  40 + @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
  41 + public CommonResult<List<CrmStatisticsPerformanceRespVO>> getContractPriceStaffPerformance(@Valid CrmStatisticsPerformanceReqVO performanceReqVO) {
  42 + return success(performanceService.getContractPricePerformance(performanceReqVO));
  43 + }
  44 +
  45 + @GetMapping("/get-receivable-price-performance")
  46 + @Operation(summary = "员工业绩-获得回款金额")
  47 + @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
  48 + public CommonResult<List<CrmStatisticsPerformanceRespVO>> getReceivablePriceStaffPerformance(@Valid CrmStatisticsPerformanceReqVO performanceReqVO) {
  49 + return success(performanceService.getReceivablePricePerformance(performanceReqVO));
  50 + }
  51 +
  52 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import jakarta.validation.constraints.NotEmpty;
  8 +import jakarta.validation.constraints.NotNull;
  9 +import java.time.LocalDateTime;
  10 +import java.util.List;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  13 +
  14 +@Schema(description = "管理后台 - CRM 员工业绩统计 Request VO")
  15 +@Data
  16 +public class CrmStatisticsPerformanceReqVO {
  17 +
  18 + @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + @NotNull(message = "部门 id 不能为空")
  20 + private Long deptId;
  21 +
  22 + /**
  23 + * 负责人用户 id, 当用户为空, 则计算部门下用户
  24 + */
  25 + @Schema(description = "负责人用户 id", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
  26 + private Long userId;
  27 +
  28 + /**
  29 + * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来
  30 + * <p>
  31 + * 后续,可能会支持选择部分用户进行查询
  32 + */
  33 + @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2")
  34 + private List<Long> userIds;
  35 +
  36 + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED)
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + @NotEmpty(message = "时间范围不能为空")
  39 + private LocalDateTime[] times;
  40 +
  41 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import java.math.BigDecimal;
  6 +
  7 +
  8 +@Schema(description = "管理后台 - CRM 员工业绩统计 Response VO")
  9 +@Data
  10 +public class CrmStatisticsPerformanceRespVO {
  11 +
  12 + @Schema(description = "时间轴", requiredMode = Schema.RequiredMode.REQUIRED, example = "202401")
  13 + private String time;
  14 +
  15 + @Schema(description = "当月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private BigDecimal currentMonthCount;
  17 +
  18 + @Schema(description = "上月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  19 + private BigDecimal lastMonthCount;
  20 +
  21 + @Schema(description = "去年同期统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
  22 + private BigDecimal lastYearCount;
  23 +
  24 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPerformanceMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
  2 +
  3 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * CRM 员工业绩分析 Mapper
  11 + *
  12 + * @author scholar
  13 + */
  14 +@Mapper
  15 +public interface CrmStatisticsPerformanceMapper {
  16 +
  17 + /**
  18 + * 员工签约合同数量
  19 + *
  20 + * @param performanceReqVO 参数
  21 + * @return 员工签约合同数量
  22 + */
  23 + List<CrmStatisticsPerformanceRespVO> selectContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
  24 +
  25 + /**
  26 + * 员工签约合同金额
  27 + *
  28 + * @param performanceReqVO 参数
  29 + * @return 员工签约合同金额
  30 + */
  31 + List<CrmStatisticsPerformanceRespVO> selectContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
  32 +
  33 + /**
  34 + * 员工回款金额
  35 + *
  36 + * @param performanceReqVO 参数
  37 + * @return 员工回款金额
  38 + */
  39 + List<CrmStatisticsPerformanceRespVO> selectReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
  40 +
  41 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.statistics;
  2 +
  3 +
  4 +
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * CRM 员工绩效统计 Service 接口
  12 + *
  13 + * @author scholar
  14 + */
  15 +public interface CrmStatisticsPerformanceService {
  16 +
  17 + /**
  18 + * 员工签约合同数量分析
  19 + *
  20 + * @param performanceReqVO 排行参数
  21 + * @return 员工签约合同数量排行分析
  22 + */
  23 + List<CrmStatisticsPerformanceRespVO> getContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
  24 +
  25 + /**
  26 + * 员工签约合同金额分析
  27 + *
  28 + * @param performanceReqVO 排行参数
  29 + * @return 员工签约合同金额分析
  30 + */
  31 + List<CrmStatisticsPerformanceRespVO> getContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
  32 +
  33 + /**
  34 + * 员工获得回款金额分析
  35 + *
  36 + * @param performanceReqVO 排行参数
  37 + * @return 员工获得回款金额分析
  38 + */
  39 + List<CrmStatisticsPerformanceRespVO> getReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
  40 +
  41 +
  42 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.statistics;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
  7 +import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPerformanceMapper;
  8 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  9 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  10 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  11 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  12 +import org.springframework.stereotype.Service;
  13 +import org.springframework.validation.annotation.Validated;
  14 +
  15 +import jakarta.annotation.Resource;
  16 +import java.util.Collections;
  17 +import java.util.List;
  18 +import java.util.function.Function;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  21 +
  22 +/**
  23 + * CRM 员工业绩分析 Service 实现类
  24 + *
  25 + * @author scholar
  26 + */
  27 +@Service
  28 +@Validated
  29 +public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerformanceService {
  30 +
  31 + @Resource
  32 + private CrmStatisticsPerformanceMapper performanceMapper;
  33 +
  34 + @Resource
  35 + private AdminUserApi adminUserApi;
  36 + @Resource
  37 + private DeptApi deptApi;
  38 +
  39 +
  40 + @Override
  41 + public List<CrmStatisticsPerformanceRespVO> getContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
  42 + return getPerformance(performanceReqVO, performanceMapper::selectContractCountPerformance);
  43 + }
  44 +
  45 + @Override
  46 + public List<CrmStatisticsPerformanceRespVO> getContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
  47 + return getPerformance(performanceReqVO, performanceMapper::selectContractPricePerformance);
  48 + }
  49 +
  50 + @Override
  51 + public List<CrmStatisticsPerformanceRespVO> getReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
  52 + return getPerformance(performanceReqVO, performanceMapper::selectReceivablePricePerformance);
  53 + }
  54 +
  55 + /**
  56 + * 获得员工业绩数据
  57 + *
  58 + * @param performanceReqVO 参数
  59 + * @param performanceFunction 排行榜方法
  60 + * @return 排行版数据
  61 + */
  62 + private List<CrmStatisticsPerformanceRespVO> getPerformance(CrmStatisticsPerformanceReqVO performanceReqVO, Function<CrmStatisticsPerformanceReqVO,
  63 + List<CrmStatisticsPerformanceRespVO>> performanceFunction) {
  64 +
  65 + // 1. 获得用户编号数组
  66 + final List<Long> userIds = getUserIds(performanceReqVO);
  67 + if (CollUtil.isEmpty(userIds)) {
  68 + return Collections.emptyList();
  69 + }
  70 + performanceReqVO.setUserIds(userIds);
  71 + // 2. 获得排行数据
  72 + List<CrmStatisticsPerformanceRespVO> performance = performanceFunction.apply(performanceReqVO);
  73 + if (CollUtil.isEmpty(performance)) {
  74 + return Collections.emptyList();
  75 + }
  76 + return performance;
  77 + }
  78 +
  79 + /**
  80 + * 获取用户编号数组。如果用户编号为空, 则获得部门下的用户编号数组,包括子部门的所有用户编号
  81 + *
  82 + * @param reqVO 请求参数
  83 + * @return 用户编号数组
  84 + */
  85 + private List<Long> getUserIds(CrmStatisticsPerformanceReqVO reqVO) {
  86 + // 情况一:选中某个用户
  87 + if (ObjUtil.isNotNull(reqVO.getUserId())) {
  88 + return List.of(reqVO.getUserId());
  89 + }
  90 + // 情况二:选中某个部门
  91 + // 2.1 获得部门列表
  92 + final Long deptId = reqVO.getDeptId();
  93 + List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
  94 + deptIds.add(deptId);
  95 + // 2.2 获得用户编号
  96 + return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
  97 + }
  98 +
  99 +}
0 100 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPerformanceMapper">
  4 +
  5 + <select id="selectContractCountPerformance"
  6 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO">
  7 + SELECT
  8 + t.time as time,
  9 + COALESCE(t.currentMonthCount,0) as currentMonthCount,
  10 + COALESCE(y.lastMonthCount,0) as lastMonthCount,
  11 + COALESCE(z.lastYearCount,0) as lastYearCount
  12 + FROM
  13 + (SELECT
  14 + COUNT(1) AS currentMonthCount,
  15 + DATE_FORMAT(order_date, '%Y-%m') AS time
  16 + FROM crm_contract
  17 + WHERE deleted = 0
  18 + AND audit_status = 20
  19 + AND owner_user_id in
  20 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  21 + #{userId}
  22 + </foreach>
  23 + AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
  24 + GROUP BY time)t
  25 + LEFT JOIN
  26 + (SELECT
  27 + COUNT(1) AS lastMonthCount,
  28 + DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 MONTH), '%Y-%m') AS time
  29 + FROM crm_contract
  30 + WHERE deleted = 0
  31 + AND audit_status = 20
  32 + AND owner_user_id in
  33 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  34 + #{userId}
  35 + </foreach>
  36 + AND (DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
  37 + or DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1)
  38 + GROUP BY time)y ON t.time = y.time
  39 + LEFT JOIN
  40 + (SELECT
  41 + COUNT(1) AS lastYearCount,
  42 + DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 YEAR), '%Y-%m') AS time
  43 + FROM crm_contract
  44 + WHERE deleted = 0
  45 + AND audit_status = 20
  46 + AND owner_user_id in
  47 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  48 + #{userId}
  49 + </foreach>
  50 + AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1
  51 + GROUP BY time)z ON t.time = z.time
  52 + </select>
  53 + <select id="selectContractPricePerformance"
  54 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO">
  55 + SELECT
  56 + t.time as time,
  57 + COALESCE(t.currentMonthCount,0) as currentMonthCount,
  58 + COALESCE(y.lastMonthCount,0) as lastMonthCount,
  59 + COALESCE(z.lastYearCount,0) as lastYearCount
  60 + FROM
  61 + (SELECT
  62 + IFNULL(SUM(total_price), 0) AS currentMonthCount,
  63 + DATE_FORMAT(order_date, '%Y-%m') AS time
  64 + FROM crm_contract
  65 + WHERE deleted = 0
  66 + AND audit_status = 20
  67 + AND owner_user_id in
  68 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  69 + #{userId}
  70 + </foreach>
  71 + AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
  72 + GROUP BY time)t
  73 + LEFT JOIN
  74 + (SELECT
  75 + IFNULL(SUM(total_price), 0) AS lastMonthCount,
  76 + DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 MONTH), '%Y-%m') AS time
  77 + FROM crm_contract
  78 + WHERE deleted = 0
  79 + AND audit_status = 20
  80 + AND owner_user_id in
  81 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  82 + #{userId}
  83 + </foreach>
  84 + AND (DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
  85 + or DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1)
  86 + GROUP BY time)y ON t.time = y.time
  87 + LEFT JOIN
  88 + (SELECT
  89 + IFNULL(SUM(total_price), 0) AS lastYearCount,
  90 + DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 YEAR), '%Y-%m') AS time
  91 + FROM crm_contract
  92 + WHERE deleted = 0
  93 + AND audit_status = 20
  94 + AND owner_user_id in
  95 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  96 + #{userId}
  97 + </foreach>
  98 + AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1
  99 + GROUP BY time)z ON t.time = z.time
  100 + </select>
  101 +
  102 + <select id="selectReceivablePricePerformance"
  103 + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO">
  104 + SELECT
  105 + t.time as time,
  106 + COALESCE(t.currentMonthCount,0) as currentMonthCount,
  107 + COALESCE(y.lastMonthCount,0) as lastMonthCount,
  108 + COALESCE(z.lastYearCount,0) as lastYearCount
  109 + FROM
  110 + (SELECT
  111 + IFNULL(SUM(price), 0) AS currentMonthCount,
  112 + DATE_FORMAT(return_time, '%Y-%m') AS time
  113 + FROM crm_receivable
  114 + WHERE deleted = 0
  115 + AND audit_status = 20
  116 + AND owner_user_id in
  117 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  118 + #{userId}
  119 + </foreach>
  120 + AND DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
  121 + GROUP BY time)t
  122 + LEFT JOIN
  123 + (SELECT
  124 + IFNULL(SUM(price), 0) AS lastMonthCount,
  125 + DATE_FORMAT(DATE_ADD(return_time,INTERVAL 1 MONTH), '%Y-%m') AS time
  126 + FROM crm_receivable
  127 + WHERE deleted = 0
  128 + AND audit_status = 20
  129 + AND owner_user_id in
  130 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  131 + #{userId}
  132 + </foreach>
  133 + AND (DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
  134 + or DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1)
  135 + GROUP BY time)y ON t.time = y.time
  136 + LEFT JOIN
  137 + (SELECT
  138 + IFNULL(SUM(price), 0) AS lastYearCount,
  139 + DATE_FORMAT(DATE_ADD(return_time,INTERVAL 1 YEAR), '%Y-%m') AS time
  140 + FROM crm_receivable
  141 + WHERE deleted = 0
  142 + AND audit_status = 20
  143 + AND owner_user_id in
  144 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  145 + #{userId}
  146 + </foreach>
  147 + AND DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1
  148 + GROUP BY time)z ON t.time = z.time
  149 + </select>
  150 +
  151 +
  152 +</mapper>
... ...