Commit 0b7d42482f449112e33b74a9b511b0c31524bcb3
1 parent
f374e778
统计:增加商品统计定时任务
Showing
10 changed files
with
206 additions
and
168 deletions
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java
| ... | ... | @@ -42,8 +42,8 @@ public interface ProductBrowseHistoryMapper extends BaseMapperX<ProductBrowseHis |
| 42 | 42 | .eqIfPresent(ProductBrowseHistoryDO::getUserDeleted, userDeleted)); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | - default Page<ProductBrowseHistoryDO> selectPageByUserIdOrderByCreateTimeAsc(Long userId) { | |
| 46 | - Page<ProductBrowseHistoryDO> page = Page.of(0, 1); | |
| 45 | + default Page<ProductBrowseHistoryDO> selectPageByUserIdOrderByCreateTimeAsc(Long userId, Integer pageNo, Integer pageSize) { | |
| 46 | + Page<ProductBrowseHistoryDO> page = Page.of(pageNo, pageSize); | |
| 47 | 47 | return selectPage(page, new LambdaQueryWrapperX<ProductBrowseHistoryDO>() |
| 48 | 48 | .eqIfPresent(ProductBrowseHistoryDO::getUserId, userId) |
| 49 | 49 | .orderByAsc(ProductBrowseHistoryDO::getCreateTime)); | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java
| ... | ... | @@ -32,8 +32,8 @@ public class ProductBrowseHistoryServiceImpl implements ProductBrowseHistoryServ |
| 32 | 32 | if (historyDO != null) { |
| 33 | 33 | browseHistoryMapper.deleteById(historyDO); |
| 34 | 34 | } else { |
| 35 | - // 情况二:限制每个用户的浏览记录的条数 | |
| 36 | - Page<ProductBrowseHistoryDO> pageResult = browseHistoryMapper.selectPageByUserIdOrderByCreateTimeAsc(userId); | |
| 35 | + // 情况二:限制每个用户的浏览记录的条数(只查一条最早地记录、记录总数) | |
| 36 | + Page<ProductBrowseHistoryDO> pageResult = browseHistoryMapper.selectPageByUserIdOrderByCreateTimeAsc(userId, 1, 1); | |
| 37 | 37 | if (pageResult.getTotal() >= USER_STORE_MAXIMUM) { |
| 38 | 38 | // 删除最早的一条 |
| 39 | 39 | browseHistoryMapper.deleteById(CollUtil.getFirst(pageResult.getRecords())); | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/product/ProductSpuStatisticsDO.java deleted
| 1 | -package cn.iocoder.yudao.module.statistics.dal.mysql.product; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 4 | -import com.baomidou.mybatisplus.annotation.KeySequence; | |
| 5 | -import com.baomidou.mybatisplus.annotation.TableId; | |
| 6 | -import com.baomidou.mybatisplus.annotation.TableName; | |
| 7 | -import lombok.*; | |
| 8 | - | |
| 9 | -import java.time.LocalDateTime; | |
| 10 | - | |
| 11 | -/** | |
| 12 | - * 商品 SPU 统计 DO | |
| 13 | - * | |
| 14 | - * 以天为维度,统计商品 SPU 的数据 | |
| 15 | - * | |
| 16 | - * @author 芋道源码 | |
| 17 | - */ | |
| 18 | -@TableName("product_spu_statistics") | |
| 19 | -@KeySequence("product_spu_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 20 | -@Data | |
| 21 | -@EqualsAndHashCode(callSuper = true) | |
| 22 | -@ToString(callSuper = true) | |
| 23 | -@Builder | |
| 24 | -@NoArgsConstructor | |
| 25 | -@AllArgsConstructor | |
| 26 | -public class ProductSpuStatisticsDO extends BaseDO { | |
| 27 | - | |
| 28 | - /** | |
| 29 | - * 编号,主键自增 | |
| 30 | - */ | |
| 31 | - @TableId | |
| 32 | - private Long id; | |
| 33 | - | |
| 34 | - /** | |
| 35 | - * 商品 SPU 编号 | |
| 36 | - * | |
| 37 | - * 关联 ProductSpuDO 的 id 字段 | |
| 38 | - */ | |
| 39 | - private Long spuId; | |
| 40 | - /** | |
| 41 | - * 统计日期 | |
| 42 | - */ | |
| 43 | - private LocalDateTime time; | |
| 44 | - | |
| 45 | - /** | |
| 46 | - * 浏览量 | |
| 47 | - */ | |
| 48 | - private Integer browseCount; | |
| 49 | - /** | |
| 50 | - * 收藏量 | |
| 51 | - */ | |
| 52 | - private Integer favoriteCount; | |
| 53 | - | |
| 54 | - /** | |
| 55 | - * 添加购物车次数 | |
| 56 | - * | |
| 57 | - * 以商品被添加到购物车的 createTime 计算,后续多次添加,不会增加该值。 | |
| 58 | - * 直到该次被下单、或者被删除,后续再次被添加到购物车。 | |
| 59 | - */ | |
| 60 | - private Integer addCartCount; | |
| 61 | - /** | |
| 62 | - * 创建订单商品数 | |
| 63 | - */ | |
| 64 | - private Integer createOrderCount; | |
| 65 | - /** | |
| 66 | - * 支付订单商品数 | |
| 67 | - */ | |
| 68 | - private Integer payOrderCount; | |
| 69 | - /** | |
| 70 | - * 总支付金额,单位:分 | |
| 71 | - */ | |
| 72 | - private Integer payPrice; | |
| 73 | - | |
| 74 | -} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/product/ProductStatisticsDO.java deleted
| 1 | -package cn.iocoder.yudao.module.statistics.dal.mysql.product; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 4 | -import com.baomidou.mybatisplus.annotation.KeySequence; | |
| 5 | -import com.baomidou.mybatisplus.annotation.TableId; | |
| 6 | -import com.baomidou.mybatisplus.annotation.TableName; | |
| 7 | -import lombok.*; | |
| 8 | - | |
| 9 | -import java.time.LocalDateTime; | |
| 10 | - | |
| 11 | -/** | |
| 12 | - * 商品统计 DO | |
| 13 | - * | |
| 14 | - * 以天为维度,统计全部的数据 | |
| 15 | - * | |
| 16 | - * 和 {@link ProductSpuStatisticsDO} 的差异是,它是全局的统计 | |
| 17 | - * | |
| 18 | - * @author 芋道源码 | |
| 19 | - */ | |
| 20 | -@TableName("product_spu_statistics") | |
| 21 | -@KeySequence("product_spu_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 22 | -@Data | |
| 23 | -@EqualsAndHashCode(callSuper = true) | |
| 24 | -@ToString(callSuper = true) | |
| 25 | -@Builder | |
| 26 | -@NoArgsConstructor | |
| 27 | -@AllArgsConstructor | |
| 28 | -public class ProductStatisticsDO extends BaseDO { | |
| 29 | - | |
| 30 | - /** | |
| 31 | - * 编号,主键自增 | |
| 32 | - */ | |
| 33 | - @TableId | |
| 34 | - private Long id; | |
| 35 | - | |
| 36 | - /** | |
| 37 | - * 统计日期 | |
| 38 | - */ | |
| 39 | - private LocalDateTime time; | |
| 40 | - | |
| 41 | - /** | |
| 42 | - * 浏览量 | |
| 43 | - */ | |
| 44 | - private Integer browseCount; | |
| 45 | - /** | |
| 46 | - * 收藏量 | |
| 47 | - */ | |
| 48 | - private Integer favoriteCount; | |
| 49 | - | |
| 50 | - /** | |
| 51 | - * 添加购物车次数 | |
| 52 | - * | |
| 53 | - * 以商品被添加到购物车的 createTime 计算,后续多次添加,不会增加该值。 | |
| 54 | - * 直到该次被下单、或者被删除,后续再次被添加到购物车。 | |
| 55 | - */ | |
| 56 | - private Integer addCartCount; | |
| 57 | - /** | |
| 58 | - * 创建订单商品数 | |
| 59 | - */ | |
| 60 | - private Integer createOrderCount; | |
| 61 | - /** | |
| 62 | - * 支付订单商品数 | |
| 63 | - */ | |
| 64 | - private Integer payOrderCount; | |
| 65 | - /** | |
| 66 | - * 总支付金额,单位:分 | |
| 67 | - */ | |
| 68 | - private Integer payPrice; | |
| 69 | - | |
| 70 | -} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/product/ProductStatisticsMapper.java
| ... | ... | @@ -3,12 +3,16 @@ package cn.iocoder.yudao.module.statistics.dal.mysql.product; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; |
| 5 | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 6 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | 7 | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| 7 | 8 | import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsReqVO; |
| 8 | 9 | import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsRespVO; |
| 9 | 10 | import cn.iocoder.yudao.module.statistics.dal.dataobject.product.ProductStatisticsDO; |
| 11 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
| 10 | 12 | import org.apache.ibatis.annotations.Mapper; |
| 13 | +import org.apache.ibatis.annotations.Param; | |
| 11 | 14 | |
| 15 | +import java.time.LocalDateTime; | |
| 12 | 16 | import java.util.List; |
| 13 | 17 | |
| 14 | 18 | /** |
| ... | ... | @@ -57,4 +61,20 @@ public interface ProductStatisticsMapper extends BaseMapperX<ProductStatisticsDO |
| 57 | 61 | .selectAvg(ProductStatisticsDO::getBrowseConvertPercent); |
| 58 | 62 | } |
| 59 | 63 | |
| 64 | + /** | |
| 65 | + * 根据时间范围统计商品信息 | |
| 66 | + * | |
| 67 | + * @param page 分页参数 | |
| 68 | + * @param beginTime 起始时间 | |
| 69 | + * @param endTime 截止时间 | |
| 70 | + * @return 统计 | |
| 71 | + */ | |
| 72 | + IPage<ProductStatisticsDO> selectStatisticsResultPageByTimeBetween(IPage<ProductStatisticsDO> page, | |
| 73 | + @Param("beginTime") LocalDateTime beginTime, | |
| 74 | + @Param("endTime") LocalDateTime endTime); | |
| 75 | + | |
| 76 | + default Long selectCountByTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { | |
| 77 | + return selectCount(new LambdaQueryWrapperX<ProductStatisticsDO>().between(ProductStatisticsDO::getTime, beginTime, endTime)); | |
| 78 | + } | |
| 79 | + | |
| 60 | 80 | } |
| 61 | 81 | \ No newline at end of file | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/job/product/ProductStatisticsJob.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.job.product; | |
| 2 | + | |
| 3 | +import cn.hutool.core.convert.Convert; | |
| 4 | +import cn.hutool.core.util.NumberUtil; | |
| 5 | +import cn.hutool.core.util.ObjUtil; | |
| 6 | +import cn.hutool.core.util.StrUtil; | |
| 7 | +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; | |
| 8 | +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; | |
| 9 | +import cn.iocoder.yudao.module.statistics.service.product.ProductStatisticsService; | |
| 10 | +import jakarta.annotation.Resource; | |
| 11 | +import org.springframework.stereotype.Component; | |
| 12 | + | |
| 13 | +// TODO 芋艿:缺个 Job 的配置;等和 Product 一起配置 | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 商品统计 Job | |
| 17 | + * | |
| 18 | + * @author owen | |
| 19 | + */ | |
| 20 | +@Component | |
| 21 | +public class ProductStatisticsJob implements JobHandler { | |
| 22 | + | |
| 23 | + @Resource | |
| 24 | + private ProductStatisticsService productStatisticsService; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 执行商品统计任务 | |
| 28 | + * | |
| 29 | + * @param param 要统计的天数,只能是正整数,1 代表昨日数据 | |
| 30 | + * @return 统计结果 | |
| 31 | + */ | |
| 32 | + @Override | |
| 33 | + @TenantJob | |
| 34 | + public String execute(String param) { | |
| 35 | + // 默认昨日 | |
| 36 | + param = ObjUtil.defaultIfBlank(param, "1"); | |
| 37 | + // 校验参数的合理性 | |
| 38 | + if (!NumberUtil.isInteger(param)) { | |
| 39 | + throw new RuntimeException("商品统计任务的参数只能为是正整数"); | |
| 40 | + } | |
| 41 | + Integer days = Convert.toInt(param, 0); | |
| 42 | + if (days < 1) { | |
| 43 | + throw new RuntimeException("商品统计任务的参数只能为是正整数"); | |
| 44 | + } | |
| 45 | + String result = productStatisticsService.statisticsProduct(days); | |
| 46 | + return StrUtil.format("商品统计:\n{}", result); | |
| 47 | + } | |
| 48 | +} | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsService.java
| ... | ... | @@ -17,14 +17,6 @@ import java.util.List; |
| 17 | 17 | public interface ProductStatisticsService { |
| 18 | 18 | |
| 19 | 19 | /** |
| 20 | - * 创建商品统计 | |
| 21 | - * | |
| 22 | - * @param entity 创建信息 | |
| 23 | - * @return 编号 | |
| 24 | - */ | |
| 25 | - Long createProductStatistics(ProductStatisticsDO entity); | |
| 26 | - | |
| 27 | - /** | |
| 28 | 20 | * 获得商品统计排行榜分页 |
| 29 | 21 | * |
| 30 | 22 | * @param reqVO 查询条件 |
| ... | ... | @@ -49,4 +41,11 @@ public interface ProductStatisticsService { |
| 49 | 41 | */ |
| 50 | 42 | List<ProductStatisticsDO> getProductStatisticsList(ProductStatisticsReqVO reqVO); |
| 51 | 43 | |
| 44 | + /** | |
| 45 | + * 统计指定天数的商品数据 | |
| 46 | + * | |
| 47 | + * @return 统计结果 | |
| 48 | + */ | |
| 49 | + String statisticsProduct(Integer days); | |
| 50 | + | |
| 52 | 51 | } |
| 53 | 52 | \ No newline at end of file | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.statistics.service.product; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.date.DatePattern; | |
| 5 | +import cn.hutool.core.date.LocalDateTimeUtil; | |
| 3 | 6 | import cn.hutool.core.util.ArrayUtil; |
| 4 | 7 | import cn.hutool.core.util.ObjUtil; |
| 5 | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| ... | ... | @@ -10,13 +13,18 @@ import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductSta |
| 10 | 13 | import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsRespVO; |
| 11 | 14 | import cn.iocoder.yudao.module.statistics.dal.dataobject.product.ProductStatisticsDO; |
| 12 | 15 | import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductStatisticsMapper; |
| 16 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
| 17 | +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |
| 13 | 18 | import jakarta.annotation.Resource; |
| 14 | 19 | import org.springframework.stereotype.Service; |
| 20 | +import org.springframework.util.StopWatch; | |
| 15 | 21 | import org.springframework.validation.annotation.Validated; |
| 16 | 22 | |
| 17 | 23 | import java.time.Duration; |
| 18 | 24 | import java.time.LocalDateTime; |
| 19 | 25 | import java.util.List; |
| 26 | +import java.util.stream.Collectors; | |
| 27 | +import java.util.stream.IntStream; | |
| 20 | 28 | |
| 21 | 29 | |
| 22 | 30 | /** |
| ... | ... | @@ -31,17 +39,6 @@ public class ProductStatisticsServiceImpl implements ProductStatisticsService { |
| 31 | 39 | @Resource |
| 32 | 40 | private ProductStatisticsMapper productStatisticsMapper; |
| 33 | 41 | |
| 34 | - @Override | |
| 35 | - public Long createProductStatistics(ProductStatisticsDO entity) { | |
| 36 | - // 计算 访客支付转化率(百分比) | |
| 37 | - if (entity.getBrowseUserCount() != null && ObjUtil.notEqual(entity.getBrowseUserCount(), 0)) { | |
| 38 | - entity.setBrowseConvertPercent(100 * entity.getOrderPayCount() / entity.getBrowseUserCount()); | |
| 39 | - } | |
| 40 | - // 插入 | |
| 41 | - productStatisticsMapper.insert(entity); | |
| 42 | - // 返回 | |
| 43 | - return entity.getId(); | |
| 44 | - } | |
| 45 | 42 | |
| 46 | 43 | @Override |
| 47 | 44 | public PageResult<ProductStatisticsDO> getProductStatisticsRankPage(ProductStatisticsReqVO reqVO, SortablePageParam pageParam) { |
| ... | ... | @@ -69,4 +66,58 @@ public class ProductStatisticsServiceImpl implements ProductStatisticsService { |
| 69 | 66 | return productStatisticsMapper.selectListByTimeBetween(reqVO); |
| 70 | 67 | } |
| 71 | 68 | |
| 69 | + @Override | |
| 70 | + public String statisticsProduct(Integer days) { | |
| 71 | + LocalDateTime today = LocalDateTime.now(); | |
| 72 | + return IntStream.rangeClosed(1, days) | |
| 73 | + .mapToObj(day -> statisticsProduct(today.minusDays(day))) | |
| 74 | + .sorted() | |
| 75 | + .collect(Collectors.joining("\n")); | |
| 76 | + } | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * 统计商品数据 | |
| 80 | + * | |
| 81 | + * @param date 需要统计的日期 | |
| 82 | + * @return 统计结果 | |
| 83 | + */ | |
| 84 | + private String statisticsProduct(LocalDateTime date) { | |
| 85 | + // 1. 处理统计时间范围 | |
| 86 | + LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(date); | |
| 87 | + LocalDateTime endTime = LocalDateTimeUtil.endOfDay(date); | |
| 88 | + String dateStr = DatePattern.NORM_DATE_FORMATTER.format(date); | |
| 89 | + // 2. 检查该日是否已经统计过 | |
| 90 | + Long count = productStatisticsMapper.selectCountByTimeBetween(beginTime, endTime); | |
| 91 | + if (count != null && count > 0) { | |
| 92 | + return dateStr + " 数据已存在,如果需要重新统计,请先删除对应的数据"; | |
| 93 | + } | |
| 94 | + | |
| 95 | + // 3. 统计数据 | |
| 96 | + StopWatch stopWatch = new StopWatch(dateStr); | |
| 97 | + stopWatch.start(); | |
| 98 | + | |
| 99 | + // 分页统计,避免商品表数据较多时,出现超时问题 | |
| 100 | + final int pageSize = 100; | |
| 101 | + for (int pageNo = 1; ; pageNo ++) { | |
| 102 | + IPage<ProductStatisticsDO> page = productStatisticsMapper.selectStatisticsResultPageByTimeBetween( | |
| 103 | + Page.of(pageNo, pageSize, false), beginTime, endTime); | |
| 104 | + if (CollUtil.isEmpty(page.getRecords())) { | |
| 105 | + break; | |
| 106 | + } | |
| 107 | + | |
| 108 | + for (ProductStatisticsDO record : page.getRecords()) { | |
| 109 | + record.setTime(date.toLocalDate()); | |
| 110 | + // 计算 访客支付转化率(百分比) | |
| 111 | + if (record.getBrowseUserCount() != null && ObjUtil.notEqual(record.getBrowseUserCount(), 0)) { | |
| 112 | + record.setBrowseConvertPercent(100 * record.getOrderPayCount() / record.getBrowseUserCount()); | |
| 113 | + } | |
| 114 | + } | |
| 115 | + | |
| 116 | + // 4. 插入数据 | |
| 117 | + productStatisticsMapper.insertBatch(page.getRecords()); | |
| 118 | + } | |
| 119 | + | |
| 120 | + return stopWatch.prettyPrint(); | |
| 121 | + } | |
| 122 | + | |
| 72 | 123 | } |
| 73 | 124 | \ No newline at end of file | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java
| ... | ... | @@ -99,7 +99,7 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { |
| 99 | 99 | // 1. 处理统计时间范围 |
| 100 | 100 | LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(date); |
| 101 | 101 | LocalDateTime endTime = LocalDateTimeUtil.endOfDay(date); |
| 102 | - String dateStr = DatePattern.NORM_DATE_FORMAT.format(date); | |
| 102 | + String dateStr = DatePattern.NORM_DATE_FORMATTER.format(date); | |
| 103 | 103 | // 2. 检查该日是否已经统计过 |
| 104 | 104 | TradeStatisticsDO entity = tradeStatisticsMapper.selectByTimeBetween(beginTime, endTime); |
| 105 | 105 | if (entity != null) { | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/product/ProductStatisticsMapper.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.statistics.dal.mysql.product.ProductStatisticsMapper"> | |
| 4 | + | |
| 5 | + <select id="selectStatisticsResultPageByTimeBetween" | |
| 6 | + resultType="cn.iocoder.yudao.module.statistics.dal.dataobject.product.ProductStatisticsDO"> | |
| 7 | + SELECT spu.id AS spuId | |
| 8 | + -- 浏览量:一个用户可以有多次 | |
| 9 | + , (SELECT COUNT(1) | |
| 10 | + FROM product_browse_history | |
| 11 | + WHERE spu_id = spu.id | |
| 12 | + AND create_time BETWEEN #{beginTime} AND #{endTime}) AS browse_count | |
| 13 | + -- 访客量:按用户去重计数 | |
| 14 | + , (SELECT COUNT(DISTINCT user_id) | |
| 15 | + FROM product_browse_history | |
| 16 | + WHERE spu_id = spu.id | |
| 17 | + AND create_time BETWEEN #{beginTime} AND #{endTime}) AS browse_user_count | |
| 18 | + -- 收藏数量:按用户去重计数 | |
| 19 | + , (SELECT COUNT(DISTINCT user_id) | |
| 20 | + FROM product_favorite | |
| 21 | + WHERE spu_id = spu.id | |
| 22 | + AND create_time BETWEEN #{beginTime} AND #{endTime}) AS favorite_count | |
| 23 | + -- 加购数量:按用户去重计数 | |
| 24 | + , (SELECT COUNT(DISTINCT user_id) | |
| 25 | + FROM trade_cart | |
| 26 | + WHERE spu_id = spu.id | |
| 27 | + AND create_time BETWEEN #{beginTime} AND #{endTime}) AS cart_count | |
| 28 | + -- 下单件数 | |
| 29 | + , (SELECT IFNULL(SUM(count), 0) | |
| 30 | + FROM trade_order_item | |
| 31 | + WHERE spu_id = spu.id | |
| 32 | + AND create_time BETWEEN #{beginTime} AND #{endTime}) AS order_count | |
| 33 | + -- 支付件数 | |
| 34 | + , (SELECT IFNULL(SUM(item.count), 0) | |
| 35 | + FROM trade_order_item item | |
| 36 | + JOIN trade_order o ON item.order_id = o.id | |
| 37 | + WHERE spu_id = spu.id | |
| 38 | + AND o.pay_status = TRUE | |
| 39 | + AND item.create_time BETWEEN #{beginTime} AND #{endTime}) AS order_pay_count | |
| 40 | + -- 支付金额 | |
| 41 | + , (SELECT IFNULL(SUM(item.pay_price), 0) | |
| 42 | + FROM trade_order_item item | |
| 43 | + JOIN trade_order o ON item.order_id = o.id | |
| 44 | + WHERE spu_id = spu.id | |
| 45 | + AND o.pay_status = TRUE | |
| 46 | + AND item.create_time BETWEEN #{beginTime} AND #{endTime}) AS order_pay_price | |
| 47 | + -- 退款件数 | |
| 48 | + , (SELECT IFNULL(SUM(count), 0) | |
| 49 | + FROM trade_after_sale | |
| 50 | + WHERE spu_id = spu.id | |
| 51 | + AND refund_time IS NOT NULL | |
| 52 | + AND create_time BETWEEN #{beginTime} AND #{endTime}) AS after_sale_count | |
| 53 | + -- 退款金额 | |
| 54 | + , (SELECT IFNULL(SUM(refund_price), 0) | |
| 55 | + FROM trade_after_sale | |
| 56 | + WHERE spu_id = spu.id | |
| 57 | + AND refund_time IS NOT NULL | |
| 58 | + AND create_time BETWEEN #{beginTime} AND #{endTime}) AS after_sale_refund_price | |
| 59 | + FROM product_spu spu | |
| 60 | + WHERE spu.deleted = FALSE | |
| 61 | + ORDER BY spu.id | |
| 62 | + </select> | |
| 63 | + | |
| 64 | +</mapper> | ... | ... |