分析页统计:1、小板数据源name完善,宽高厚小数点0移除,用x连接;2、x轴日类型修改;3、小板排名前10逻辑错误修复;

This commit is contained in:
gaoqr
2024-08-15 18:26:47 +08:00
parent 982be46985
commit 4428dbedc3
6 changed files with 178 additions and 86 deletions
@@ -86,4 +86,11 @@ public class OrderStatisticsController {
public CommonResult<Map<String,Object>> getPlateArea(@Valid OrderStatisticsReqVO reqVO) { public CommonResult<Map<String,Object>> getPlateArea(@Valid OrderStatisticsReqVO reqVO) {
return success(orderStatisticsService.getOrderPlateAreaGroup(reqVO)); return success(orderStatisticsService.getOrderPlateAreaGroup(reqVO));
} }
@GetMapping("/bigPlateCount/group")
@Operation(summary = "大板数量分组统计")
public CommonResult<Map<String, Object>> getBigPlateCount(@Valid OrderStatisticsReqVO reqVO) {
return success(null);
}
} }
@@ -61,40 +61,32 @@ public class OrderGoodsPlateRespVO implements Comparable<OrderGoodsPlateRespVO>
@Override @Override
public int compareTo(@NotNull OrderGoodsPlateRespVO other) { public int compareTo(@NotNull OrderGoodsPlateRespVO other) {
// 解析 date 字符串为年、月、周 if (orderDate != null && other.orderDate != null) {
String[] partsThis = orderDate.split("-"); // 解析 date 字符串为年、月、周
String[] partsOther = other.orderDate.split("-"); String[] partsThis = orderDate.split("-");
String[] partsOther = other.orderDate.split("-");
// 比较年份 // 比较年份
int yearComparison = Integer.compare(Integer.parseInt(partsThis[0]), Integer.parseInt(partsOther[0])); int yearComparison = Integer.compare(Integer.parseInt(partsThis[0]), Integer.parseInt(partsOther[0]));
if (yearComparison != 0) { if (yearComparison != 0) {
return yearComparison; return yearComparison;
}
// 比较月份
if (partsThis.length > 1 && partsOther.length > 1) {
int monthComparison = Integer.compare(Integer.parseInt(partsThis[1]), Integer.parseInt(partsOther[1]));
if (monthComparison != 0) {
return monthComparison;
} }
}
// 比较周/日 // 比较月份
if (partsThis.length > 2 && partsOther.length > 2) { if (partsThis.length + partsOther.length > 2) {
int weekComparison = Integer.compare(Integer.parseInt(partsThis[2]), Integer.parseInt(partsOther[2])); int monthComparison = Integer.compare(Integer.parseInt(partsThis[1]), Integer.parseInt(partsOther[1]));
if (weekComparison != 0) { if (monthComparison != 0) {
return weekComparison; return monthComparison;
}
} }
}
// 比较数量 // 比较周/日
if (orderCount != null && other.orderCount != null) { if (partsThis.length + partsOther.length > 4) {
return orderCount.compareTo(other.orderCount); int weekComparison = Integer.compare(Integer.parseInt(partsThis[2]), Integer.parseInt(partsOther[2]));
} if (weekComparison != 0) {
return weekComparison;
// 比较面积 }
if (orderArea != null && other.orderArea != null) { }
return orderArea.compareTo(other.orderArea);
} }
return 0; return 0;
} }
@@ -21,6 +21,9 @@ public class OptimizeBoardModelDO extends ESDocument {
@Schema(description = "排单ID") @Schema(description = "排单ID")
private Long planId; private Long planId;
@Schema(description ="排单优化的大板数里")
private Long placeBoardNumber;
@Schema(description = "生产单id") @Schema(description = "生产单id")
private Long orderId; private Long orderId;
@@ -18,19 +18,37 @@ import java.util.List;
@Mapper @Mapper
public interface OrderPlateStatisticsMapper extends BaseMapperX<PlateDO> { public interface OrderPlateStatisticsMapper extends BaseMapperX<PlateDO> {
/** /**
* 基于生产单时间分组统计小板数量 * 基于商品id分组的小板数量列表
* *
* @param reqVO * @param reqVO
* @return * @return
*/ */
List<OrderGoodsPlateRespVO> selectPlateAnalysisListByCount(@Param("req") OrderStatisticsReqVO reqVO); List<OrderGoodsPlateRespVO> selectPlateCountList(@Param("req") OrderStatisticsReqVO reqVO);
/** /**
* 基于生产单时间分组统计小板面积 * 基于订单日期分组的前10小板数量分组
* @param goodsIdList
* @param reqVO
* @return
*/
List<OrderGoodsPlateRespVO> selectTopTenPlateCountListGroupByOrderDate(@Param("goodsIds") List<Long> goodsIdList, @Param("req") OrderStatisticsReqVO reqVO);
/**
* 基于商品id分组的小板面积列表
* @param reqVO
* @return
*/
List<OrderGoodsPlateRespVO> selectPlateAreaList(@Param("req") OrderStatisticsReqVO reqVO);
/**
* 基于订单日期分组的前10小板面积分组
* *
* @param reqVO * @param reqVO
* @return * @return
*/ */
List<OrderGoodsPlateRespVO> selectPlateAnalysisListByArea(@Param("req") OrderStatisticsReqVO reqVO); List<OrderGoodsPlateRespVO> selectTopTenPlateAreaListGroupByOrderDate(@Param("goodsIds") List<Long> goodsIdList, @Param("req") OrderStatisticsReqVO reqVO);
} }
@@ -12,6 +12,9 @@ import com.cf.imes.module.executor.dal.mysql.order.OrderStatisticsMapper;
import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper; import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper;
import com.cf.imes.module.executor.dal.mysql.plate.OrderPlateStatisticsMapper; import com.cf.imes.module.executor.dal.mysql.plate.OrderPlateStatisticsMapper;
import com.cf.imes.module.executor.enums.OrderStatisticsUnit; import com.cf.imes.module.executor.enums.OrderStatisticsUnit;
import com.cf.imes.module.system.api.dict.DictDataApi;
import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO;
import com.cf.imes.module.system.enums.DictTypeConstants;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -47,6 +50,9 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
@Resource @Resource
private OrderPlateStatisticsMapper orderPlateStatisticsMapper; private OrderPlateStatisticsMapper orderPlateStatisticsMapper;
@Resource
private DictDataApi dictDataApi;
// 常用的字段key // 常用的字段key
private static final String DATELIST_FIELD_NAME = "dateList"; private static final String DATELIST_FIELD_NAME = "dateList";
private static final String SERIES_FIELD_NAME = "series"; private static final String SERIES_FIELD_NAME = "series";
@@ -200,22 +206,33 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
// 所有的日期集合 // 所有的日期集合
List<String> dateList = getDateList(reqVO); List<String> dateList = getDateList(reqVO);
List<OrderGoodsPlateRespVO> orderGoodsPlateRespVOList = orderPlateStatisticsMapper.selectPlateAnalysisListByCount(reqVO); // 查询时间段内数量最多的小板,排序列出数量前10的goods_id
// 基于相同的orderDate分组 List<Long> topTenCountGoodsId = orderPlateStatisticsMapper.selectPlateCountList(reqVO).stream()
Map<String, List<OrderGoodsPlateRespVO>> orderGoodsPlateRespMap = orderGoodsPlateRespVOList.stream() .sorted(Comparator.comparingLong(OrderGoodsPlateRespVO::getOrderCount).reversed())
.map(OrderGoodsPlateRespVO::getGoodsId)
.limit(10)
.collect(Collectors.toList());
// 前十goods_id基于时间分组
Map<String, List<OrderGoodsPlateRespVO>> orderGoodsPlateRespMap = orderPlateStatisticsMapper.selectTopTenPlateCountListGroupByOrderDate(topTenCountGoodsId, reqVO).stream()
.sorted(Comparator.naturalOrder()) .sorted(Comparator.naturalOrder())
.collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList())); .collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList()));
// 获取所有商品map // 获取所有商品{goodsId:respvo},根据top10排序
Map<Long, OrderGoodsPlateRespVO> goodsMap = orderGoodsPlateRespMap.values().stream() Map<Long, OrderGoodsPlateRespVO> goodsMap = new LinkedHashMap<>();
.flatMap(List::stream) for (Long id : topTenCountGoodsId) {
.collect(Collectors.toMap( List<OrderGoodsPlateRespVO> list = orderGoodsPlateRespMap.values().stream()
OrderGoodsPlateRespVO::getGoodsId, .flatMap(List::stream)
vo -> vo, .filter(vo -> vo.getGoodsId().equals(id))
(oldValue, newValue) -> oldValue .collect(Collectors.toList());
)); if (!list.isEmpty()) {
// goodsId相同,其他属性任取
goodsMap.put(id, list.get(0));
}
}
// 遍历订单状态所有枚举值 // 遍历所有goods_id
List<Map<String, Object>> series = new ArrayList<>(); List<Map<String, Object>> series = new ArrayList<>();
for (Map.Entry<Long, OrderGoodsPlateRespVO> entry : goodsMap.entrySet()) { for (Map.Entry<Long, OrderGoodsPlateRespVO> entry : goodsMap.entrySet()) {
Map<String, Object> seriesItem = new HashMap<>(); Map<String, Object> seriesItem = new HashMap<>();
@@ -228,10 +245,10 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
List<OrderGoodsPlateRespVO> orderGoodsPlateRespVOS = orderGoodsPlateRespMap.get(dateStr); List<OrderGoodsPlateRespVO> orderGoodsPlateRespVOS = orderGoodsPlateRespMap.get(dateStr);
int count = 0; int count = 0;
if (orderGoodsPlateRespVOS != null) { if (orderGoodsPlateRespVOS != null) {
count = orderGoodsPlateRespVOS.stream() Optional<OrderGoodsPlateRespVO> matchingRespVO = orderGoodsPlateRespVOS.stream()
.filter(respVO -> Objects.equals(entry.getKey(), respVO.getGoodsId())) .filter(respVO -> Objects.equals(entry.getKey(), respVO.getGoodsId()))
.map(OrderGoodsPlateRespVO::getOrderCount) .findFirst();
.findFirst().orElse(0); count = matchingRespVO.map(OrderGoodsPlateRespVO::getOrderCount).orElse(0);
} }
sumArr[index++] = count; sumArr[index++] = count;
} }
@@ -240,9 +257,12 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
seriesItem.put("id", entry.getKey()); seriesItem.put("id", entry.getKey());
// 材质-商品名称-颜色-纹理-宽-高-厚-品牌 // 材质-商品名称-颜色-纹理-宽-高-厚-品牌
OrderGoodsPlateRespVO orderGoodsPlateRespVO = entry.getValue(); OrderGoodsPlateRespVO orderGoodsPlateRespVO = entry.getValue();
// 获取纹路描述
DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.GRAIN_TYPE, String.valueOf(orderGoodsPlateRespVO.getTexture())).getData();
String texture = ObjectUtil.isNotNull(grainDTO) ? grainDTO.getLabel() : "";
seriesItem.put("name", orderGoodsPlateRespVO.getMaterial() + "-" + orderGoodsPlateRespVO.getGoodsName() + seriesItem.put("name", orderGoodsPlateRespVO.getMaterial() + "-" + orderGoodsPlateRespVO.getGoodsName() +
"-" + orderGoodsPlateRespVO.getColor() + "-" + orderGoodsPlateRespVO.getTexture() + "-" + orderGoodsPlateRespVO.getWidth() + "-" + orderGoodsPlateRespVO.getColor() + "-" + texture + "-" + stripTrailingZeros(orderGoodsPlateRespVO.getWidth()) +
"-" + orderGoodsPlateRespVO.getHeight() + "-" + orderGoodsPlateRespVO.getThickness() + "-" + orderGoodsPlateRespVO.getBrand()); "×" + stripTrailingZeros(orderGoodsPlateRespVO.getHeight()) + "×" + stripTrailingZeros(orderGoodsPlateRespVO.getThickness()) + "-" + orderGoodsPlateRespVO.getBrand());
series.add(seriesItem); series.add(seriesItem);
} }
resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, reqVO.getUnit())).toList()); resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, reqVO.getUnit())).toList());
@@ -257,22 +277,33 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
// 所有的日期集合 // 所有的日期集合
List<String> dateList = getDateList(reqVO); List<String> dateList = getDateList(reqVO);
List<OrderGoodsPlateRespVO> orderGoodsPlateRespVOList = orderPlateStatisticsMapper.selectPlateAnalysisListByArea(reqVO); // 查询时间段内面积最多的小板,排序列出前10面积的goods_id
// 基于相同的orderDate分组 List<Long> topTenCountGoodsId = orderPlateStatisticsMapper.selectPlateAreaList(reqVO).stream()
Map<String, List<OrderGoodsPlateRespVO>> orderGoodsPlateRespMap = orderGoodsPlateRespVOList.stream() .sorted(Comparator.comparing(OrderGoodsPlateRespVO::getOrderArea).reversed())
.map(OrderGoodsPlateRespVO::getGoodsId)
.limit(10)
.collect(Collectors.toList());
// 前十goods_id基于时间分组
Map<String, List<OrderGoodsPlateRespVO>> orderGoodsPlateRespMap = orderPlateStatisticsMapper.selectTopTenPlateAreaListGroupByOrderDate(topTenCountGoodsId, reqVO).stream()
.sorted(Comparator.naturalOrder()) .sorted(Comparator.naturalOrder())
.collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList())); .collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList()));
// 获取所有商品map // 获取所有商品{goodsId:respvo},根据top10排序
Map<Long, OrderGoodsPlateRespVO> goodsMap = orderGoodsPlateRespMap.values().stream() Map<Long, OrderGoodsPlateRespVO> goodsMap = new LinkedHashMap<>();
.flatMap(List::stream) for (Long id : topTenCountGoodsId) {
.collect(Collectors.toMap( List<OrderGoodsPlateRespVO> list = orderGoodsPlateRespMap.values().stream()
OrderGoodsPlateRespVO::getGoodsId, .flatMap(List::stream)
vo -> vo, .filter(vo -> vo.getGoodsId().equals(id))
(oldValue, newValue) -> newValue .collect(Collectors.toList());
)); if (!list.isEmpty()) {
// goodsId相同,其他属性任取
goodsMap.put(id, list.get(0));
}
}
// 遍历订单状态所有枚举值 // 遍历所有goods_id
List<Map<String, Object>> series = new ArrayList<>(); List<Map<String, Object>> series = new ArrayList<>();
for (Map.Entry<Long, OrderGoodsPlateRespVO> entry : goodsMap.entrySet()) { for (Map.Entry<Long, OrderGoodsPlateRespVO> entry : goodsMap.entrySet()) {
Map<String, Object> seriesItem = new HashMap<>(); Map<String, Object> seriesItem = new HashMap<>();
@@ -287,7 +318,7 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
if (orderGoodsPlateRespVOS != null) { if (orderGoodsPlateRespVOS != null) {
area = orderGoodsPlateRespVOS.stream() area = orderGoodsPlateRespVOS.stream()
.filter(respVO -> Objects.equals(entry.getKey(), respVO.getGoodsId())) .filter(respVO -> Objects.equals(entry.getKey(), respVO.getGoodsId()))
.map(OrderGoodsPlateRespVO::getOrderArea) .map(vo -> vo.getOrderArea().stripTrailingZeros())
.findFirst().orElse(new BigDecimal(0)); .findFirst().orElse(new BigDecimal(0));
} }
areaArr[index++] = area; areaArr[index++] = area;
@@ -297,9 +328,12 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
seriesItem.put("id", entry.getKey()); seriesItem.put("id", entry.getKey());
// 材质-商品名称-颜色-纹理-宽-高-厚-品牌 // 材质-商品名称-颜色-纹理-宽-高-厚-品牌
OrderGoodsPlateRespVO orderGoodsPlateRespVO = entry.getValue(); OrderGoodsPlateRespVO orderGoodsPlateRespVO = entry.getValue();
// 获取纹路描述
DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.GRAIN_TYPE, String.valueOf(orderGoodsPlateRespVO.getTexture())).getData();
String texture = ObjectUtil.isNotNull(grainDTO) ? grainDTO.getLabel() : "";
seriesItem.put("name", orderGoodsPlateRespVO.getMaterial() + "-" + orderGoodsPlateRespVO.getGoodsName() + seriesItem.put("name", orderGoodsPlateRespVO.getMaterial() + "-" + orderGoodsPlateRespVO.getGoodsName() +
"-" + orderGoodsPlateRespVO.getColor() + "-" + orderGoodsPlateRespVO.getTexture() + "-" + orderGoodsPlateRespVO.getWidth() + "-" + orderGoodsPlateRespVO.getColor() + "-" + texture + "-" + stripTrailingZeros(orderGoodsPlateRespVO.getWidth()) +
"-" + orderGoodsPlateRespVO.getHeight() + "-" + orderGoodsPlateRespVO.getThickness() + "-" + orderGoodsPlateRespVO.getBrand()); "×" + stripTrailingZeros(orderGoodsPlateRespVO.getHeight()) + "×" + stripTrailingZeros(orderGoodsPlateRespVO.getThickness()) + "-" + orderGoodsPlateRespVO.getBrand());
series.add(seriesItem); series.add(seriesItem);
} }
resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, reqVO.getUnit())).toList()); resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, reqVO.getUnit())).toList());
@@ -435,11 +469,25 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
newDateStrBuffer.append("").append(dateSplit[2]).append(""); newDateStrBuffer.append("").append(dateSplit[2]).append("");
break; break;
case DAY: case DAY:
newDateStrBuffer.append(dateSplit[2]).append(""); newDateStrBuffer.append(dateSplit[2]);
break; break;
default: default:
} }
return newDateStrBuffer.toString(); return newDateStrBuffer.toString();
} }
/**
* 移除尾数的0600.000 -> 600
*
* @param data
* @return
*/
private String stripTrailingZeros(BigDecimal data) {
if (ObjectUtil.isNotNull(data)) {
return data.stripTrailingZeros().toPlainString();
} else {
return "";
}
}
} }
@@ -1,7 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cf.imes.module.executor.dal.mysql.plate.OrderPlateStatisticsMapper"> <mapper namespace="com.cf.imes.module.executor.dal.mysql.plate.OrderPlateStatisticsMapper">
<select id="selectPlateAnalysisListByCount" resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO"> <select id="selectPlateCountList" resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO">
select g.goods_id,
count(a.id) as orderCount
from order_goods g
left join order_plate a ON g.id = a.goods_id and a.deleted = 0
left join orders o ON o.id = a.order_id and o.deleted = 0
where g.deleted = 0
and o.order_date between #{req.createTime[0]} and #{req.createTime[1]}
group by g.goods_id
having orderCount > 0
order by null;
</select>
<select id="selectTopTenPlateCountListGroupByOrderDate" resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO">
SELECT g.goods_id, SELECT g.goods_id,
MIN(g.material) AS material, MIN(g.material) AS material,
MIN(g.brand) AS brand, MIN(g.brand) AS brand,
@@ -26,20 +39,32 @@
,CONCAT(YEAR(o.order_date), '-', MONTH(o.order_date), '-', DAY(o.order_date)) as orderDate ,CONCAT(YEAR(o.order_date), '-', MONTH(o.order_date), '-', DAY(o.order_date)) as orderDate
</if> </if>
FROM order_goods g FROM order_goods g
LEFT JOIN order_plate a ON g.id = a.goods_id LEFT JOIN order_plate a ON g.id = a.goods_id and a.deleted = 0
LEFT JOIN orders o ON o.id = a.order_id LEFT JOIN orders o ON o.id = a.order_id and o.deleted = 0
WHERE a.deleted = 0 WHERE g.deleted = 0
AND o.order_date BETWEEN #{req.createTime[0]} AND #{req.createTime[1]} AND o.order_date BETWEEN #{req.createTime[0]} AND #{req.createTime[1]}
and g.goods_id in
<foreach item="goodsId" collection="goodsIds" open="(" separator="," close=")">
#{goodsId}
</foreach>
GROUP BY GROUP BY
g.goods_id,orderDate g.goods_id,orderDate;
HAVING
orderCount > 0
ORDER BY
orderCount DESC
LIMIT 10;
</select> </select>
<select id="selectPlateAnalysisListByArea" <select id="selectPlateAreaList" resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO">
select g.goods_id,
SUM(a.area) AS orderArea
from order_goods g
left join order_plate a ON g.id = a.goods_id and a.deleted = 0
left join orders o ON o.id = a.order_id and o.deleted = 0
where g.deleted = 0
and o.order_date between #{req.createTime[0]} and #{req.createTime[1]}
group by g.goods_id
having orderArea > 0
order by null;
</select>
<select id="selectTopTenPlateAreaListGroupByOrderDate"
resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO"> resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO">
SELECT g.goods_id, SELECT g.goods_id,
MIN(g.material) AS material, MIN(g.material) AS material,
@@ -65,16 +90,15 @@
,CONCAT(YEAR(o.order_date), '-', MONTH(o.order_date), '-', DAY(o.order_date)) as orderDate ,CONCAT(YEAR(o.order_date), '-', MONTH(o.order_date), '-', DAY(o.order_date)) as orderDate
</if> </if>
FROM order_goods g FROM order_goods g
LEFT JOIN order_plate a ON g.id = a.goods_id LEFT JOIN order_plate a ON g.id = a.goods_id and a.deleted = 0
LEFT JOIN orders o ON o.id = a.order_id LEFT JOIN orders o ON o.id = a.order_id and o.deleted = 0
WHERE a.deleted = 0 WHERE g.deleted = 0
AND o.order_date BETWEEN #{req.createTime[0]} AND #{req.createTime[1]} AND o.order_date BETWEEN #{req.createTime[0]} AND #{req.createTime[1]}
and g.goods_id in
<foreach item="goodsId" collection="goodsIds" open="(" separator="," close=")">
#{goodsId}
</foreach>
GROUP BY GROUP BY
g.goods_id,orderDate g.goods_id,orderDate;
HAVING
orderArea > 0
ORDER BY
orderArea DESC
LIMIT 10;
</select> </select>
</mapper> </mapper>