问题背景

在一个多表查询的sql中正常情况下产生的数据都是唯一的,但因为数据库中存在错误(某张表中存在相同的外键ID)导致我这边查询出来的数据就会有重复的问题
下面结果集中UserID:15834存在多个
 
查询Sql如下:
  1. SELECT *
  2. FROM (
  3. SELECT ROW_NUMBER() OVER ( ORDER BY T.USERID asc )AS Row
  4. ,T.USERID
  5. ,T.CreateTime
  6. FROM UserInfo T
  7. LEFT JOIN DiseaseInfo i ON i.UserID=T.UserID
  8. ) TT WHERE TT.Row between 0 AND 20 ORDER BY UserID DESC
解决方法:
参考下面新的解决方案
在网络上了解到MSSql中通过关键字“PARTITION BY”可以将查询结果集进行分区处理,然后在查询结果集时就可以过滤掉重复的记录了(如果有指定分区字段则区ID相同)
通过更改后的Sql,在Over中添加PARTITION BY T.USERID以UserID进行分区,然后在查询结果集时通过DISTINCT ROW ,过滤掉重复的分区ID号
  1. SELECT DISTINCT ROW ,*
  2. FROM (
  3. SELECT ROW_NUMBER() OVER (PARTITION BY T.USERID ORDER BY T.USERID asc )AS Row
  4. ,T.USERID
  5. ,T.CreateTime
  6. FROM UserInfo T
  7. LEFT JOIN DiseaseInfo i ON i.UserID=T.UserID
  8. ) TT WHERE TT.Row between 0 AND 12 ORDER BY UserID DESC
查询时未过滤重复分区IDDISTINCT ROW ,下面的结果集跟上面的结果集不同(Row是进行过分区的所有有重复Row)
   
 
在查询结果集时过滤掉重复的分区ID号 DISTINCT ROW ,
 
 
 
新解决方案:
 
由于在Sqlserver中如果多表联合查询中除非所有的字段都完全相同否则在使用DISTINCT 用进行去重时还是会当成两个不同的数据集进行处理,因此DISTINCT会失效即
如下面的结果集,虽然 USERID和其他字段内容相同但HID是不相同的所以无法使用DISTINCT进行去重
出现这种问题是因为数据库设计的错误(正常情况下关联表 HospitalInfo中只可能存在一条ClinicInfo表对应的记录)
Sql语句:
  1. SELECT *
  2. FROM (
  3. SELECT ROW_NUMBER() OVER ( order by T.USERID asc )AS Row
  4. ,T.USERID
  5. ,LEFT(T.Patient_Tel1,5)+'' AS Tel
  6. ,T.CreateTime
  7. ,h.HName
  8. ,h.HID
  9. fromUserInfo T
  10. LEFT JOIN ClinicInfo c ON c.UserID=T.UserID AND C.Disabled=1
  11. LEFT JOIN HospitalInfo H ON H.HID=c.VisitHospital WHERE T.Disabled=1
  12. AND t.UserID>=17867 AND T.UserID<=17875
  13. --(T.Patient_Tel1 like '%13800000000%')
  14. ) TT WHERE
  15. TT.Row between 0and20
 
可以看到上面的结果集中Row是有重复的,其他Row为2的是跟第一个是重复的
 
因为数据库涉及到其他业务和人员因此我只能提交该问题给相关的技术,但在该问题解决前不能影响到我这边也出现此问题
于是在原sql基础上进行处理,虽然HospitalInfo表中不重复记录但表的自增ID是不可能重复的那我只需要最新的一条记录即可
 
如果通过DISTINCT过进行去重则就无法成功,因为数据存在差别,可以看到第一条和最后一条数据还是重复的
  1. SELECT DISTINCT row,*
  2. FROM (
  3. SELECT ROW_NUMBER() OVER ( partition by T.USERID order by T.USERID asc )AS Row
  4. ,T.USERID
  5. ,LEFT(T.Patient_Tel1,5)+'' AS Tel
  6. ,T.CreateTime
  7. ,h.HName
  8. ,h.HID
  9. fromUserInfo T
  10. LEFT JOIN ClinicInfo c ON c.UserID=T.UserID AND C.Disabled=1
  11. LEFT JOIN HospitalInfo H ON H.HID=c.VisitHospital WHERE T.Disabled=1
  12. AND t.UserID>=17867 AND T.UserID<=17875
  13. --(T.Patient_Tel1 like '%13800000000%')
  14. ) TT WHERE
  15. --row=1 AND
  16. TT.Row between 0 and 20
 
更改后的Sql
 
  1. SELECT *
  2. FROM (
  3. --partition by T.USERID UserID对结果集进行分区
  4. SELECT ROW_NUMBER() OVER ( partition by T.USERID order by T.USERID asc )AS Row
  5. ,T.USERID
  6. ,LEFT(T.Patient_Tel1,5)+'' AS Tel
  7. ,T.CreateTime
  8. ,h.HName
  9. ,h.HID
  10. fromUserInfo T
  11. LEFT JOIN ClinicInfo c ON c.UserID=T.UserID AND C.Disabled=1
  12. LEFT JOIN HospitalInfo H ON H.HID=c.VisitHospital WHERE T.Disabled=1
  13. AND t.UserID>=17867 AND T.UserID<=17875
  14. --(T.Patient_Tel1 like '%13800000000%')
  15. ) TT WHERE
  16. --因为之前已经以UserID对结果集进行分区,所以如果存在重复的字段则row的值会不相同
  17. --row=1 AND
  18.  
  19. TT.Row between 0 and 20
USERID=17867相同经过分区后会存在不同的Row值
 
在对结果集再次过滤时添加条件 : row=1,已经将重复记录中旧的数据过滤掉了 (HID:78)
 
 
根据新的解决方案解决了重复的问题,但又出现的新的问题即Row分区后都是重复的,而我再进行分页的时候就无效了(因为此时结果集中的Row都是为1)
解决方案:在结果集再加一层查询并加上ID号然后再对结果集进行分页处理
 
  1. -- 新增一层查询解决过滤掉重复数据后无法分页的问题
  2. SELECT * FROM (
  3. SELECT ROW_NUMBER() OVER (ORDER BY userid) AS RowNum,*
  4. FROM (
  5. --partition by T.USERID UserID对结果集进行分区
  6. SELECT ROW_NUMBER() OVER ( partition by T.USERID order by T.USERID asc )AS Row
  7. ,T.USERID
  8. ,LEFT(T.Patient_Tel1,5)+'' AS Tel
  9. ,T.CreateTime
  10. ,h.HName
  11. ,h.HID
  12. fromUserInfo T
  13. LEFT JOIN ClinicInfo c ON c.UserID=T.UserID AND C.Disabled=1
  14. LEFT JOIN HospitalInfo H ON H.HID=c.VisitHospital WHERE T.Disabled=1
  15. AND t.UserID>=17867 AND T.UserID<=20875
  16. --(T.Patient_Tel1 like '%13800000000%')
  17. ) TT
  18. )AS T
  19. WHERE
  20. --过滤重复数据
  21. Row=1
  22. --对结果进行分页
  23. AND RowNum between 13 and 24
 
参考:

SqlServer 在查询结果中如何过滤掉重复数据的更多相关文章

  1. MySQL查询表中某个字段的重复数据

    1. 查询SQL表中某个字段的重复数据 SELECT user_name,COUNT(*) AS count FROM db_user_info GROUP BY user_name HAVING c ...

  2. mysql去重, 把url重复且区为空的中去掉、统计重复数据、、结果集去重合并成一行

    delete from 表名 where id not in (select d.id from (SELECT id FROM 表名 GROUP BY c1,c2,c3,c4)as d) #去重复, ...

  3. Mysql中查找并删除重复数据的方法

    (一)单个字段 1.查找表中多余的重复记录,根据(question_title)字段来判断 代码如下 复制代码 select * from questions where question_title ...

  4. 查询Oracle中字段名带"."的数据

    SDE中的TT_L线层会有SHAPE.LEN这样的字段,使用: SQL>select shape.len from tt_l; 或 SQL>select t.shape.len from ...

  5. SQL-游标-查询数据库中的所有表的数据个数

    --sql语句-游标等使用 ) ) declare @i INT ) declare @cstucount INT --上方设置变量 --初始值 declare mCursor cursor --设置 ...

  6. 用java查询HBase中某表的一批数据

    java代码如下: package db.query; import java.io.IOException; import org.apache.hadoop.conf.Configuration; ...

  7. 【SQL】查询数据库中某个字段有重复值出现的信息

    select name,mobile from [GeneShop].[dbo].[xx_member] where mobile in ( SELECT mobile FROM [GeneShop] ...

  8. mysql查询sql中检索条件为大批量数据时处理

    当userIdArr数组值为大批量时,应如此优化代码实现

  9. Java中List集合去除重复数据的方法

    1. 循环list中的所有元素然后删除重复 public static List removeDuplicate(List list) { for ( int i = 0 ; i < list. ...

随机推荐

  1. hdu1527下沙小面的(二)

    B - 下沙小面的(2) Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit ...

  2. 【BZOJ 3470】3470: Freda’s Walk 期望

    3470: Freda’s Walk Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 42  Solved: 22 Description 雨后的Poet ...

  3. 直接插入排序(初级版)之C++实现

    直接插入排序(初级版)之C++实现 一.源代码:InsertSortLow.cpp /*直接插入排序思想: 假设待排序的记录存放在数组R[1..n]中.初始时,R[1]自成1个有序区,无序区为R[2. ...

  4. [BZOJ4561][JLOI2016]圆的异或并(扫描线)

    考虑任何一条垂直于x轴的直线,由于圆不交,所以这条直线上的圆弧构成形似括号序列的样子,且直线移动时圆之间的相对位置不变. 将每个圆拆成两边,左端加右端删.每次加圆时考虑它外面最内层的括号属于谁.用se ...

  5. Azure ServiceBus的消息中带有@strin3http//schemas.microsoft.com/2003/10/Serialization/�

    今天碰到一个很讨厌的问题,使用nodejs 接收Azure service bus队列消息的时候,出现了:@strin3http//schemas.microsoft.com/2003/10/Seri ...

  6. 【ACM-ICPC 2018 徐州赛区网络预赛】E. End Fantasy VIX 血辣 (矩阵运算的推广)

    Morgana is playing a game called End Fantasy VIX. In this game, characters have nn skills, every ski ...

  7. 【原】MySQL实用SQL积累

    [文档简述] 本文档用来记录一些常用的SQL语句,以达到快速查询的目的. [常用SQL] 1.mysql数据库中获取某个表的所有字段名 select COLUMN_NAME from informat ...

  8. ActiveMQ Cluster (ActiveMQ 集群) 配置

    构建高可用的ActiveMQ系统在生产环境中是非常重要的,对于这个apache的消息中间件实现高可用非常简单,只要在Apache ActiveMQ单点基本配置基础上做一次配置变更(如果在一台设备上部署 ...

  9. Reverse Engineering the NC ECU (revisited) -- SH7508

    http://forum.miata.net/vb/showthread.php?t=536601 Hey all! About 5 years ago, there was a great thre ...

  10. ASP.NET Web API教程 分页查询

    首先增加支持分页的API方法 public IEnumerable<UserInfo> GetUserInfos(int pageindex, int size)         {    ...