当使用A字段排序时(A字段不是索引字段),不论是升序排列还是降序排列,如果不显示指定最后使用id字段排序,分页还是会出现重复数据问题。
当使用A字段排序时(A字段是索引字段),不论是升序排列还是降序排列,如果不显示指定最后使用id字段排序,分页还是会出现重复数据问题。
也就是说,不论字段A是不是索引字段,不论A是升序降序,如果不显示指定第二排序字段,数据库分页查询还是会出现重复问题。也就是说默认的主键排序并没有生效。
结果(result):
通过今天的案例,让我们学习到了,数据库使用order by给查询结果排序时是不稳定的,我们指定排序字段时应该尽量选择区分度比较大的字段,如果第一排序字段区分度不够大,则可以考虑增加第二排序字段。
同时,今天也借此机会验证了,MySQL数据库order by排序时,默认使用主键索引作为隐形的最后排序字段在这个分页过程中并没有生效。
写个函数吧灵活点。
v_str1 是实际记录
v_str2 是现实的记录,如果v_str1中没有要显示的记录(如南京路)返回空
create or replace function f_test(v_str1 in varchar2, v_str2 in varchar2)
return varchar2 as
n_instr int;
begin
n_instr := instr(v_str1, v_str2);
if n_instr > 0 then
return v_str2;
else
return '';
end if;
end;
--测试
select f_test('南京路,淮海路,天津路,古美路','南京路') col
from dual;
--结果
南京路
select f_test('淮海路,天津路,古美路','南京路') col
from dual;
结果
空
select replace(replace(字段名称,chr(13),''),chr(10),'') from table_name
回车符的ASCII码13
换行是10
问题背景
在一个多表查询的sql中正常情况下产生的数据都是唯一的,但因为数据库中存在错误(某张表中存在相同的外键ID)导致我这边查询出来的数据就会有重复的问题
下面结果集中UserID:15834存在多个
查询Sql如下:
SELECT FROM (SELECT ROW_NUMBER() OVER ( ORDER BY TUSERID asc )AS Row
,TUSERID
,TCreateTimeFROM UserInfo TLEFT JOIN DiseaseInfo i ON iUserID=TUserID
) TT WHERE TTRow between 0 AND 20 ORDER BY UserID DESC
解决方法:
参考下面新的解决方案
在网络上了解到MSSql中通过关键字“PARTITION BY”可以将查询结果集进行分区处理,然后在查询结果集时就可以过滤掉重复的记录了(如果有指定分区字段则区ID相同)
通过更改后的Sql,在Over中添加PARTITION BY TUSERID以UserID进行分区,然后在查询结果集时通过DISTINCT ROW ,过滤掉重复的分区ID号
SELECT DISTINCT ROW ,FROM (SELECT ROW_NUMBER() OVER (PARTITION BY TUSERID ORDER BY TUSERID asc )AS Row
,TUSERID
,TCreateTimeFROM UserInfo TLEFT JOIN DiseaseInfo i ON iUserID=TUserID
) TT WHERE TTRow between 0 AND 12 ORDER BY UserID DESC
查询时未过滤重复分区IDDISTINCT ROW ,下面的结果集跟上面的结果集不同(Row是进行过分区的所有有重复Row)
在查询结果集时过滤掉重复的分区ID号 DISTINCT ROW ,
新解决方案:
由于在Sqlserver中如果多表联合查询中除非所有的字段都完全相同否则在使用DISTINCT 用进行去重时还是会当成两个不同的数据集进行处理,因此DISTINCT会失效即
如下面的结果集,虽然 USERID和其他字段内容相同但HID是不相同的所以无法使用DISTINCT进行去重
出现这种问题是因为数据库设计的错误(正常情况下关联表HospitalInfo中只可能存在一条ClinicInfo表对应的记录)
Sql语句:
SELECT FROM (SELECT ROW_NUMBER() OVER ( order by TUSERID asc )AS Row
,TUSERID
,LEFT(TPatient_Tel1,5)+'00000000' AS Tel
,TCreateTime
,hHName
,hHID
fromUserInfo TLEFT JOIN ClinicInfo c ON cUserID=TUserID AND CDisabled=1LEFT JOIN HospitalInfo H ON HHID=cVisitHospital WHERE TDisabled=1AND tUserID>=17867 AND TUserID<=17875--(TPatient_Tel1 like '%13800000000%')) TT WHERETTRow between 0and20
可以看到上面的结果集中Row是有重复的,其他Row为2的是跟第一个是重复的
因为数据库涉及到其他业务和人员因此我只能提交该问题给相关的技术,但在该问题解决前不能影响到我这边也出现此问题
于是在原sql基础上进行处理,虽然HospitalInfo表中不重复记录但表的自增ID是不可能重复的那我只需要最新的一条记录即可
如果通过DISTINCT过进行去重则就无法成功,因为数据存在差别,可以看到第一条和最后一条数据还是重复的
SELECT DISTINCT row,FROM (SELECT ROW_NUMBER() OVER ( partition by TUSERID order by TUSERID asc )AS Row
,TUSERID
,LEFT(TPatient_Tel1,5)+'00000000' AS Tel
,TCreateTime
,hHName
,hHID
fromUserInfo TLEFT JOIN ClinicInfo c ON cUserID=TUserID AND CDisabled=1LEFT JOIN HospitalInfo H ON HHID=cVisitHospital WHERE TDisabled=1AND tUserID>=17867 AND TUserID<=17875--(TPatient_Tel1 like '%13800000000%')) TT WHERE--row=1 ANDTTRow between 0 and 20
更改后的Sql
SELECT FROM (--partition by TUSERID 以UserID对结果集进行分区SELECT ROW_NUMBER() OVER ( partition by TUSERID order by TUSERID asc )AS Row
,TUSERID
,LEFT(TPatient_Tel1,5)+'00000000' AS Tel
,TCreateTime
,hHName
,hHID
fromUserInfo TLEFT JOIN ClinicInfo c ON cUserID=TUserID AND CDisabled=1LEFT JOIN HospitalInfo H ON HHID=cVisitHospital WHERE TDisabled=1AND tUserID>=17867 AND TUserID<=17875--(TPatient_Tel1 like '%13800000000%')) TT WHERE--因为之前已经以UserID对结果集进行分区,所以如果存在重复的字段则row的值会不相同--row=1 ANDTTRow between 0 and 20
USERID=17867相同经过分区后会存在不同的Row值
在对结果集再次过滤时添加条件 : row=1,已经将重复记录中旧的数据过滤掉了 (HID:78)
根据新的解决方案解决了重复的问题,但又出现的新的问题即Row分区后都是重复的,而我再进行分页的时候就无效了(因为此时结果集中的Row都是为1)
解决方案:在结果集再加一层查询并加上ID号然后再对结果集进行分页处理
-- 新增一层查询解决过滤掉重复数据后无法分页的问题SELECT FROM (SELECT ROW_NUMBER() OVER (ORDER BY userid) AS RowNum,FROM (--partition by TUSERID 以UserID对结果集进行分区SELECT ROW_NUMBER() OVER ( partition by TUSERID order by TUSERID asc )AS Row
,TUSERID
,LEFT(TPatient_Tel1,5)+'00000000' AS Tel
,TCreateTime
,hHName
,hHID
fromUserInfo TLEFT JOIN ClinicInfo c ON cUserID=TUserID AND CDisabled=1LEFT JOIN HospitalInfo H ON HHID=cVisitHospital WHERE TDisabled=1AND tUserID>=17867 AND TUserID<=20875--(TPatient_Tel1 like '%13800000000%')) TT
)AS TWHERE--过滤重复数据Row=1--对结果进行分页AND RowNum between 13 and 24
参考:
MSDN: OVER 子句 (Transact-SQL)
stackoverflow sql query distinct with Row_Number
SQL Trick: row_number() is to SELECT what dense_rank() is to SELECT DISTINCT
你的表述我没看得太清, “根据type类型的不同” 统计是否忽略了city_id
最好 举个例子说明一下期望的算法
我根据你的表述,猜测你这里包含两层分组业务,
第一,根据city_id进行分组, 后用分组结果进行比较再次统计
如果你是10g或以上,可以试试以下语句
with grp1 as ( select sum(ws_succ)ssucc, sum(ws_stat) sstat ,city_id ,type
from tab_open_success_ratio
where ws_stat>0
group by city_id ,type)
select sum(ssucc)10000/sum(sstat),sum(sstat),type
from grp1
group by type
MySQL 过滤重复数据
有些 MySQL 数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据。
如果你需要读取不重复的数据可以在 SELECT 语句中使用 DISTINCT 关键字来过滤重复数据。
from 树懒学堂- 一站式数据知识学习平台
你也可以使用 GROUP BY 来读取数据表中不重复的数据:
复审表通过一次自连接筛选出最大值后再做关联
SELECT花名册工号,
花名册姓名,
取证情况证书信息,
复审情况F复审时间
FROM
花名册
LEFT JOIN 取证情况 ON 花名册工号 = 取证情况工号
LEFT JOIN (
SELECT 复审情况 FROM 复审情况
INNER JOIN
(SELECT MAX(复审时间) 复审时间,工号 FROM 复审情况 GROUP BY 工号) 复审情况2
ON 复审情况复审时间=复审情况2复审时间 AND 复审情况工号=复审情况2工号
) 复审情况F ON 花名册工号 = 复审情况F工号;
以上就是关于m'd'b数据库排序过滤重复的问题全部的内容,包括:m'd'b数据库排序过滤重复的问题、请问如何在数据库中提取数据时过滤数据内容、查询数据库数据时过滤掉文本字段中的换行符或者是回车符,让查询出来的文本字段对应的内容中没有换行符等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)