两张表数据合并显示,还要分页?

4 篇文章 0 订阅

这个问题说起来挺难受的,假设表table1和table2是两个不同的表,但是基本该有的字段一致,除了有几个字段不同,由于历史的遗留的设计原因,不知道到你已经第几手代码(此时你想骂娘,我也想。我就遇上了。)

奇葩的需求是:前端UI设计师要求一个列表页面同时要显示两表的数据(要分页)。说白了就是后端实际两张表,前端UI设计师看来就是一张表的数据,呵呵,必须分页啊,两张表分页?难搞哦,话说来,分库分表中间件才会遇上的事情被你遇上了。好了,我们开干。

  • 2023-12-12:另一种思路理论,使用UNION查询(先查询相同的列),其余的列,分页之后多线程循环处理。

分析:

//①表示table1
//②表示table2

//假设某一次分页查询:pageSize = 5,currentPage = 1
//假设一:①有数据11条,pageSize = 5,currentPage = 1,①数据5条够了,不需要②来凑
//假设二:①有数据10条,pageSize = 5,currentPage = 1,①数据5条够了,不需要②来凑

//假设某一次分页查询:pageSize = 5,currentPage = 3
//假设三:①有数据11条,pageSize = 5,currentPage = 3,①数据1条不够了,需要②来凑4条
//假设四:①有数据10条,pageSize = 5,currentPage = 3,①数据不需要,全部在②里面5条

//假设某一次分页查询:pageSize = 5,currentPage = 4
//假设五:①有数据11条,pageSize = 5,currentPage = 4,不需要①来凑,全部在②里面5条
//假设六:①有数据10条,pageSize = 5,currentPage = 4,不需要①来凑,全部在②里面5条

//int countTable1 = 11;
//int countTable2 = 11;
// 11 - 5 * 1 = 6
// 11 - 5 * 2 = 1
// 11 - 5 * 3 = -4
// 11 - 5 * 4 = -9
// int countTable1 = 10;
// int countTable2 = 11;
// 10 - 5 * 1 = 5
// 10 - 5 * 2 = 0
// 10 - 5 * 3 = -5
// 10 - 5 * 4 = -10

代码按照分析的情况展开(部分关键代码):

//参数
//int currentPage
//int pageSize
//待返回的信息
List<Map<String, Object>> listAll = new ArrayList<>();
int listCount = 0;
Map<String, Object> back = new HashMap<>();

int countTable1 = `select count(*) from table1`;
int countTable2 = `select count(*) from table2`;

//检验:总数等于0,直接返回
listCount = countTable1 + countTable2;
if( listCount <= 0){
    //无数据
    back.put("list",listAll);
	back.put("listCount",listCount);
	return back;
}

//开始业务逻辑
int fillPage = countTable1 - pageSize * currentPage;
//是不是需要下一部分table2?
if(fillPage < 0){
	//fillPage < 0 需要下一部分table2!
	//转为正数
	int fillPageTemp = -fillPage;
	//需要下一部分table2多少?
	if(fillPageTemp % pageSize == 0){
		//********************************************
		// 需要下一部分table2一整页:(全部在table2)
		//********************************************
		currentPage = currentPage - ((int)(countTable1 / pageSize));
		currentPage = (currentPage - 1) * pageSize;
		pageSize = pageSize;
	
		listAll = `select * from table2 limit #{currentPage} ,#{pageSize}`
	}else{
		  if(fillPageTemp < pageSize){
			  int currentPageOriginal = currentPage;
			  int pageSizeOriginal = pageSize;
			  //********************************************
			  //一部分table1
			  //********************************************
			  currentPage = currentPage;
			  currentPage = (currentPage - 1) * pageSize;
			  pageSize = pageSize - fillPageTemp;
	
			  List<Map<String, Object>> listTable1 = `select * from table1 limit #{currentPage} ,#{pageSize}`
			  //********************************************
			  //一部分table2
			  //********************************************
			  currentPageOriginal = currentPageOriginal - ((int)(countTable1 / pageSize));
			  currentPageOriginal = (currentPageOriginal - 1) * pageSize;
			  if(currentPageOriginal <= 0){currentPageOriginal = 0;}
			  pageSizeOriginal = fillPageTemp;
	
			  List<Map<String, Object>> listTable2 = `select * from table2 limit #{currentPageOriginal} ,#{pageSizeOriginal}`
	          //合并
	          listAll.addAll(listTable1);
	          listAll.addAll(listTable2);
		  }else{
		      //********************************************
			  //(全部在table2)
			  //********************************************
			  currentPage = currentPage - ((int)(countTable1 / pageSize));
			  currentPage = (currentPage - 1) * pageSize;
			  //向前移动
			  currentPage = currentPage - (countTable1 - pageSize * ((int)(countTable1 / pageSize)));
			  pageSize = pageSize;
	
			  listAll = `select * from table2 limit #{currentPage } ,#{pageSize }`
		  }
	}
}else{
    //********************************************
	//TODO fillPage >= 0 当前table1部分足够了:(数据全部在table1)
	//********************************************
	currentPage = (currentPage - 1) * pageSize;
	pageSize = pageSize;
	
	listAll = `select * from table1 limit #{currentPage} ,#{pageSize}`
}

 //返回
 back.put("list",listAll);
 back.put("listCount",listCount);
 return back;
可以使用Elasticsearch的聚合(aggregation)功能来实现先分组统计数据的需求。具体步骤如下: 1. 使用terms aggregation进行分组 使用terms aggregation可以对某个字段进行分组,例如对于一个包含商品信息的索引,可以使用如下的聚合语句对商品按照类别进行分组: ``` GET /product_index/_search { "size": 0, "aggs": { "group_by_category": { "terms": { "field": "category.keyword", "size": 10 } } } } ``` 上述聚合语句将对`product_index`中的所有文档按照`category`字段进行分组,并统计各个分组的文档个数。 2. 使用metric aggregation进行统计 在分组的基础上,可以使用metric aggregation进行数据统计。例如,可以使用sum aggregation计算每个分组的销售总额: ``` GET /product_index/_search { "size": 0, "aggs": { "group_by_category": { "terms": { "field": "category.keyword", "size": 10 }, "aggs": { "total_sales": { "sum": { "field": "sales" } } } } } } ``` 上述聚合语句将对`product_index`中的所有文档按照`category`字段进行分组,并计算每个分组的`sales`字段的总和。 3. 使用from和size参数进行分页 最后,可以使用from和size参数进行分页。例如,如果要显示第11-20条数据,可以将from设置为10,size设置为10: ``` GET /product_index/_search { "from": 10, "size": 10, "aggs": { "group_by_category": { "terms": { "field": "category.keyword", "size": 10 }, "aggs": { "total_sales": { "sum": { "field": "sales" } } } } } } ``` 上述聚合语句将对`product_index`中的所有文档按照`category`字段进行分组,并计算每个分组的`sales`字段的总和,最后返回第11-20条数据
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值