今天项目测试运行的时候,遇到了一个奇怪的问题,这个问题说起来按sql语法的话是没有错误的

但是呢按照我们的业务来做区分就有些逻辑上的错误了,

下面请听我慢慢道来,在数据库中有两个数据,

先来看下第一次sql是如何写的

查询之后在外面做分页,很正常的逻辑,但是大家都发现了,这是一个多表查询,而且是一对多关系,这就有点问题了

先来看一个图

问题出现在哪呢?

1、需要对主表做分页数据查询,  如:

    limit 1,10 或 SELECT * FROM (SELECT A.* ,ROWNUM R FROM (select _ from car) A WHERE ROWNUM <= ${limitEnd} ) B WHERE R >= ${limitStart} ]

以上是对上表做数据统计,然后分页,

2、根据传入字段做筛选,如:车辆的座位数,排量,

出现的问题

  因为业务数据庞大,一对多关系数据冗余,出现数据偏移

主要解决思路如下

嗯,下来个图示吧

1、对子表合并,做行转列, 2、在主表做分页筛选时就不会出现,因为一对多关系数据冗余,出现数据偏移

 SELECT * FROM (SELECT A.* ,ROWNUM R FROM (

          select
T_CAR."ID" as car_ID , T_CAR."CAR_NAME" as car_CAR_NAME , T_CAR."VIN_NUMBER"
as car_VIN_NUMBER ,car_label.label_ids
FROM T_CAR
left join (select CAR_ID,wm_concat(LABLE_ID) as label_ids from T_Car_label group by CAR_ID) car_label on car_label.CAR_ID = T_CAR.ID
where FIND_IN_SET('4aa06d2b9e904fe8bfeba3505c5dad6a',label_ids)=1
) A WHERE ROWNUM <=10 ) B WHERE R >=

FIND_IN_SET:由于写在sql里的筛选很繁琐,此方法是一个储存函数 这个实现不是很好

此函数在mysql下有定义,但是此处因为与业务相关,内部做了一些更改

具体修改是当传进了一个{1,2,3,4}格式的数据时也可以做出条件筛选

create or replace FUNCTION FIND_IN_SET(piv_str1 varchar2, piv_str2 varchar2, p_sep varchar2 := ',')
RETURN NUMBER IS
l_idx_a number:=0; -- 用于计算piv_str1中分隔符的位置
l_idx_b number:=0; -- 用于计算piv_str2中分隔符的位置
str_a varchar2(4000); -- 根据分隔符截取的子字符串
str_b varchar2(4000); -- 根据分隔符截取的子字符串
piv_str_a varchar2(4000) := piv_str1; -- 将piv_str1赋值给piv_str_a
piv_str_b varchar2(4000) := piv_str2; -- 将piv_str2赋值给piv_str_b
res number:=0; -- 返回结果
BEGIN
-- 如果piv_str_a中没有分割符,直接循环判断piv_str_a和piv_str_b是否相等,相等 res=1
IF instr(piv_str_a, p_sep, 1) = 0 THEN
-- 如果piv_str2中没有分割符,直接判断piv_str1和piv_str2是否相等,相等 res=1
IF instr(piv_str_b, p_sep, 1) = 0 THEN
IF piv_str_a = piv_str_b THEN
res:= 1;
END IF;
ELSE
-- 循环按分隔符截取piv_str_b
LOOP
l_idx_b := instr(piv_str_b,p_sep);
-- 当piv_str中还有分隔符时
IF l_idx_b > 0 THEN
-- 截取第一个分隔符前的字段str
str_a:= substr(piv_str_b,1,l_idx_b-1);
-- 判断 str 和piv_str_a 是否相等,相等 res=1 并结束循环判断
IF str_a = piv_str_a THEN
res:= 1;
EXIT;
END IF;
piv_str_b := substr(piv_str_b,l_idx_b+length(p_sep));
ELSE
-- 当截取后的piv_str 中不存在分割符时,判断piv_str和piv_str1是否相等,相等 res=1
IF piv_str_a = piv_str_b THEN
res:= 1;
END IF;
-- 无论最后是否相等,都跳出循环
EXIT;
END IF;
END LOOP;
-- 结束循环
END IF;
ELSE
-- 循环按分隔符截取piv_str_a
LOOP
l_idx_a := instr(piv_str_a,p_sep);
-- 当piv_str_a中还有分隔符时
IF l_idx_a > 0 THEN
-- 截取第一个分隔符前的字段str
str_a:= substr(piv_str_a,1,l_idx_a-1);
-- 如果piv_str_b中没有分割符,直接判断piv_str1和piv_str是否相等,相等 res=1
IF instr(piv_str_b, p_sep, 1) = 0 THEN
-- 判断 str_a 和piv_str_b 是否相等,相等 res=1 并结束循环判断
IF str_a = piv_str_b THEN
res:= 1;
EXIT;
END IF;
ELSE
-- 循环按分隔符截取piv_str_b
LOOP
l_idx_b := instr(piv_str_b,p_sep);
-- 当piv_str中还有分隔符时
IF l_idx_b > 0 THEN
-- 截取第一个分隔符前的字段str
str_b:= substr(piv_str_b,1,l_idx_b-1);
-- 判断 str 和piv_str1 是否相等,相等 res=1 并结束循环判断
IF str_b = str_a THEN
res:= 1;
EXIT;
END IF;
piv_str_b := substr(piv_str_b,l_idx_b+length(p_sep));
ELSE
-- 当截取后的piv_str 中不存在分割符时,判断piv_str和piv_str1是否相等,相等 res=1
IF piv_str_a = piv_str_b THEN
res:= 1;
END IF;
-- 无论最后是否相等,都跳出循环
EXIT;
END IF;
END LOOP;
-- 结束循环
END IF;
piv_str_a := substr(piv_str_a,l_idx_a+length(p_sep));
ELSE
-- 当截取后的piv_str 中不存在分割符时,判断piv_str和piv_str1是否相等,相等 res=1
IF piv_str_a = piv_str_b THEN
res:= 1;
END IF;
-- 无论最后是否相等,都跳出循环
EXIT;
END IF;
END LOOP;
-- 结束循环
END IF;
-- 返回res
RETURN res;
END FIND_IN_SET;

  

然后完美解决

oracle 一对多数据分页查询筛选的更多相关文章

  1. 【mysql】 mybatis实现 主从表 left join 1:n 一对多 分页查询 主表从表都有查询条件 【mybatis】count 统计+JSON查询

    mybatis实现 主从表 left join  1:n 一对多 分页查询   主表从表都有查询条件+count 需求: ======================================= ...

  2. oracle入门之分页查询

    oracle的分页查询共三种方法 1.根据ROWID来分页(速率一般) SQL>select * from emp where rowid in (select rid from (select ...

  3. 【mybatis】在mybatis分页查询时,主表对关联表 一对多 分页查询怎么实现

    现在有这样一个需求: 1.积分商品分页查询 2.一个积分商品会有多张商品图片在商品图片表  1:n的关系 这样在积分商品分页查询的时候,想要顺便把每个积分商品对应的商品图片信息也带出来 实现如下: 1 ...

  4. Oracle三层嵌套分页查询示例及rownum原理

    eg:COMPONENT表数据如下 1.执行select * from (select com.*,rownum  r_num  from (select * from COMPONENT)com w ...

  5. oracle 排序后分页查询

    demo: select * from ( select * from DEV_REG_CFG_CAMERA where 1 = 1 order by unid asc) where rownum & ...

  6. oracle两种分页查询

    第一种: SELECT * FROM (SELECT A.*, ROWNUM RN FROM (SELECT * FROM table_name) A ) ; 第二种: SELECT * FROM ( ...

  7. Oracle分页查询和SQL server分页查询总结

    分页查询是项目中必不可少的一部分,难倒是不难,就是这些东西,长时间不用,就忘的一干二净了.今天特此总结一下这两款数据库分页查询的实现过程(只记录效率比较高的) 一.Oracle中的分页查询 1.通用分 ...

  8. 分页查询最好加排序(order by)

    昨天,与外部化系统对接时,发现有一个数据一直咩有集成到,双方各自排查了自己系统的代码,都觉得逻辑非常简单,无法就是一个分页查询而已. 问题就出在这个分页查询上. 为了说明当时问题发生的情景,我模拟了一 ...

  9. MySQL、Oracle和SQL Server的分页查询语句

    假设当前是第PageNo页,每页有PageSize条记录,现在分别用Mysql.Oracle和SQL Server分页查询student表. 1.Mysql的分页查询: SELECT * FROM s ...

随机推荐

  1. [MySQL Tips]:如何删除unique key约束

    [场景]: 假设最初创建了一个表bank,在street属性上添加了unique约束. create table branch( branch_name ) not null primary key, ...

  2. Python try/except/finally等

    Python try/except/finally等   x = 'abc' def fetcher(obj, index): return obj[index] fetcher(x, 4) 输出: ...

  3. c# list修改某一个属性的值

    public class info() { public string name{get;set;} public string age{get;set;} } list<info> li ...

  4. Spring Boot - Spring Data

    使用JPA 虽然JPA是一个标准,但spring中一般就是使用hibernate实现的 使用JPA(Java Persistence API,Java持久化API,是个规范,其实是借助Hibernat ...

  5. C# Po3协议读取邮件内容遇到的问题

    背景:最近在做一个小工具,读取PO3协议邮件服务器的指定人员的邮件,东西做出来了,弄了一个While死循环,20秒执行一次, 结果运行了3天,周一来IT人员找上门来了,你的电脑什么情况,怎么一个小时下 ...

  6. c# 输入姓名直到输入的是quit时,停止输入然后显示出输入的姓名个数及姓名

    1.输入姓名直到输入的是quit时(不区分大小写),停止输入然后显示出输入的姓名个数及姓名: 要求结果如下图所示: class Program { static void Main(string[] ...

  7. sql语句_统计总成绩最高的前2名

    有一个数据表,id user_id score 三个字段,计算总成绩最高的前两名 SELECT * FROM (SELECT user_name,SUM(score) AS score FROM us ...

  8. Java并发编程之final域的内存语义

    一.final域的重排序规则 对于final域,编译器和处理器要遵循两个重拍序规则: 1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序 ...

  9. webpack快速入门——插件配置:HTML文件的发布

    1.把dist中的index.html复制到src目录中,并去掉我们引入的js 2.在webpack.config.js中引入 const htmlPlugin = require('html-web ...

  10. [JavaScript] 获取数组中相同元素的个数

    /** * 获取数组中相同元素的个数 * @param val 相同的元素 * @param arr 传入数组 */ function getSameNum(val,arr){ processArr ...