关于一条查重某字段的sql语句,发现没重复的也被查出来了。。。

时间:2021-10-10 22:29:08

WITH CTE AS (
select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
from(
            select * from
               (     
                 select * from (select * from Orders) a 
                               full join (select * from PatientCome) b 
                               on a.GUID = b.ComeGUID
               ) c
               where (c.ProjectID=16 or RealProjectID=16)
                  and 
                 (
                   (convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') 
                   or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02') 
                 )
              ) d
)
SELECT * FROM CTE A
WHERE EXISTS (
SELECT 1 FROM CTE WHERE Tel = A.Tel AND RowID <> A.RowID) order by Tel


首先解释一下这段代码的意思,“表d”内部就不解释了,可以就理解成一张实表。
后面三行主要的意思就是根据RowID的不同来取出Tel字段重复的字段,最后用Tel字段进行排序。

通过这条sql语句实际测试结果表示, tel字段为空字符串的情况也算为重复了,而我希望Tel字段如果为空字符串的话,则不算重复 
注意:这里的空字符串不是NULL,而是向数据库中插入了一个空字符串。


还有一个问题,就是该sql语句查询出的结果有部分不正确,按道理Tel字段自少有两个相同的结果才对,可是取出的Tel值有些是只有一个的(也就是说其它行没有和他相同的Tel值)。 到底是什么 原因导致的呢?哪块写的不够严谨?

希望高手指点!!感激不尽!

16 个解决方案

#1


总结一下我的问题:
1.关于Tel字段中空值也认为是重复数据了,我希望Tel字段空值的情况下不算重复(注意这里的空值指的不是NULL 而是空字符串)

2.这条语句的查询结果中,按道理Tel字段自少有两个相同的结果才对,可是取出的Tel值有些是只有一个的(也就是说其它行没有和它相同的Tel值)。是哪里写的不够严谨导致的?

#2


关于一条查重某字段的sql语句,发现没重复的也被查出来了。。。高手们 你们在哪里!!

#3


给测试数据和结果

#4


lz的意思是把cte中Tel相同的记录查询出来,Tel=''的不算重复的记录?

SELECT * FROM CTE A
WHERE EXISTS (
SELECT 1 FROM CTE WHERE Tel = A.Tel AND RowID <> A.RowID and Tel <> N'') order by Tel

#5



SELECT * FROM CTE A
WHERE A.Tel <>'' and EXISTS (
SELECT 1 FROM CTE WHERE Tel = A.Tel AND RowID <> A.RowID) order by Tel


#6


感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果 

比如表d的数据如下

 tel      other
  111     11
  222      22
  111     33
  333     44
  444      55
  555      66
  666     77
  333     456
  444     88


我想得到的结果则为(顺序不一定是这样,只要按姓名排序即可)

 Name    other
   111     11
   111    33
   333     44
   333      456
   444      55
   444      88


从这个例子可以很容易看出,我想得到的数据的条件是->至少有两行或者两行以上Tel字段重复的数据,也就是说在本demo中 555是不应该出现在查询结果中的,因为555这个值在表d中只在一行中出现过。。。

但现在的问题就是出现了,测试发现在查询结果中,发现了555,按道理555本不应该在查询结果中出现,为什么?????

可能大家会怀疑我的数据会有问题,所以接下来我逐步拆分一下我的sql语句以及运行结果,下一楼我接着说,请稍等

#7


看到2个大问题:

乱用子SQL语句
乱用CTE


#8


引用 6 楼  的回复:
感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果 

比如表d的数据如下
HTML code

 tel      other
  111     11
  222      22
  111     33
  333     44
 ……



--> 测试数据:[test]
if object_id('[test]') is not null drop table [test]
create table [test]([tel] int,[other] int)
insert [test]
select 111,11 union all
select 222,22 union all
select 111,33 union all
select 333,44 union all
select 444,55 union all
select 555,66 union all
select 666,77 union all
select 333,456 union all
select 444,88

select [tel],[other] from(
select COUNT(*)over(partition by [tel]) as counts,* from test)a
where counts>=2
/*
tel other
111 33
111 11
333 456
333 44
444 55
444 88
*/

#9


首先我先说一下我说说的那个“虚拟表d”,代码如下

select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
from(
            select * from
               (     
                 select * from (select * from Orders) a 
                               full join (select * from PatientCome) b 
                               on a.GUID = b.ComeGUID
               ) c
               where (c.ProjectID=16 or RealProjectID=16)
                  and 
                 (
                   (convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') 
                   or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02') 
                 )
     ) d



现在我在真实数据中测试一下 Tel值为1381122334在“表d”*出现在多少行中 代码改写如下

select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
from(
            select * from
               (     
                 select * from (select * from Orders) a 
                               full join (select * from PatientCome) b 
                               on a.GUID = b.ComeGUID
               ) c
               where (c.ProjectID=16 or RealProjectID=16)
                  and 
                 (
                   (convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') 
                   or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02') 
                 )
     ) d
    where Tel ='1381122334'


运行结果是,只在一行中出现过,换句话说 Tel值为1381122334在“表d”中只在一行中出现过 。

接下来我整理一下发帖的那条sql语句,为了直观。可以简化成如下

WITH CTE AS (
 --表d)
SELECT * FROM CTE A
WHERE A.Tel <>'' and EXISTS (
SELECT 1 FROM CTE WHERE Tel = A.Tel AND RowID <> A.RowID) order by Tel

好了 ,记下来运行一下上面的简化代码, 结果,本不应该出现的1381122334所在行居然出现在了查询结果中。当然,得到的数据大部分结果都是正确的(也就是却是tel重复的数据都查出来了),几百条数据,也就是有那么仅有的几条出现了这种情况。

#10


引用 6 楼  的回复:
感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果 

比如表d的数据如下
HTML code

 tel      other
  111     11
  222      22
  111     33
  333     44
 ……


不要遇到问题就用CTE,找重复的完全可以避免CTE

#11


好了 我已经把整理好的需求和问题阐述清楚了,感谢楼上给出的测试代码以及建议,
但本人sql属于初学水平阶段,所以更希望高手能在我的代码基础上改一改,当然 我会尝试将测试代码理解并加在自己的sql中,但水平有限会花费很久时间 还未必能成功。。。

#12


引用 10 楼  的回复:
引用 6 楼 的回复:

感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果

比如表d的数据如下
HTML code

tel other
111 11
222 22
111 33
333 44
……

不要遇到问……

感谢你的测试代码,我已经写出来可以查询出正确结果的sql

select * from(
                select COUNT(*)over(partition by Tel) as counts,* from 
                 (
                           select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
                           from(
                                  select * from
                                  (      
                                   select * from (select * from Orders) a 
                                   full join (select * from PatientCome) b 
                                   on a.GUID = b.ComeGUID
                                  ) c
                                  where (c.ProjectID=16 or RealProjectID=16)
                                  and 
                                  ((convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02'))
                               ) d
                 ) w
             ) a
where counts>=2 and (Tel is not null) and Tel<>''

#13


你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

#14


引用 13 楼  的回复:
你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

根据你的代码 我已经写出了可以查询出正确结果的sql语句了

select * from(
                select COUNT(*)over(partition by Tel) as counts,* from 
                 (
                           select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
                           from(
                                  select * from
                                  (      
                                   select * from (select * from Orders) a 
                                   full join (select * from PatientCome) b 
                                   on a.GUID = b.ComeGUID
                                  ) c
                                  where (c.ProjectID=16 or RealProjectID=16)
                                  and 
                                  ((convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02'))
                               ) d
                 ) w
             ) a
where counts>=2 and (Tel is not null) and Tel<>N''

#15


引用 14 楼  的回复:
引用 13 楼  的回复:
你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

根据你的代码 我已经写出了可以查询出正确结果的sql语句了
SQL code

select * from(
                select COUNT(*)over(partition by Tel) as counts,* from 
……


恭喜。看代码看得头晕,所以说直接给测试数据最好。而且大家把握住你的意思也会很准确

#16


引用 15 楼  的回复:
引用 14 楼 的回复:

引用 13 楼 的回复:
你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

根据你的代码 我已经写出了可以查询出正确结果的sql语句了
SQL code

select * from(
select COUNT(*)over(partition by Tel) as counts,* from
……

呵呵 感谢你的帮助!!!好开心解决了这个问题!!!

#1


总结一下我的问题:
1.关于Tel字段中空值也认为是重复数据了,我希望Tel字段空值的情况下不算重复(注意这里的空值指的不是NULL 而是空字符串)

2.这条语句的查询结果中,按道理Tel字段自少有两个相同的结果才对,可是取出的Tel值有些是只有一个的(也就是说其它行没有和它相同的Tel值)。是哪里写的不够严谨导致的?

#2


关于一条查重某字段的sql语句,发现没重复的也被查出来了。。。高手们 你们在哪里!!

#3


给测试数据和结果

#4


lz的意思是把cte中Tel相同的记录查询出来,Tel=''的不算重复的记录?

SELECT * FROM CTE A
WHERE EXISTS (
SELECT 1 FROM CTE WHERE Tel = A.Tel AND RowID <> A.RowID and Tel <> N'') order by Tel

#5



SELECT * FROM CTE A
WHERE A.Tel <>'' and EXISTS (
SELECT 1 FROM CTE WHERE Tel = A.Tel AND RowID <> A.RowID) order by Tel


#6


感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果 

比如表d的数据如下

 tel      other
  111     11
  222      22
  111     33
  333     44
  444      55
  555      66
  666     77
  333     456
  444     88


我想得到的结果则为(顺序不一定是这样,只要按姓名排序即可)

 Name    other
   111     11
   111    33
   333     44
   333      456
   444      55
   444      88


从这个例子可以很容易看出,我想得到的数据的条件是->至少有两行或者两行以上Tel字段重复的数据,也就是说在本demo中 555是不应该出现在查询结果中的,因为555这个值在表d中只在一行中出现过。。。

但现在的问题就是出现了,测试发现在查询结果中,发现了555,按道理555本不应该在查询结果中出现,为什么?????

可能大家会怀疑我的数据会有问题,所以接下来我逐步拆分一下我的sql语句以及运行结果,下一楼我接着说,请稍等

#7


看到2个大问题:

乱用子SQL语句
乱用CTE


#8


引用 6 楼  的回复:
感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果 

比如表d的数据如下
HTML code

 tel      other
  111     11
  222      22
  111     33
  333     44
 ……



--> 测试数据:[test]
if object_id('[test]') is not null drop table [test]
create table [test]([tel] int,[other] int)
insert [test]
select 111,11 union all
select 222,22 union all
select 111,33 union all
select 333,44 union all
select 444,55 union all
select 555,66 union all
select 666,77 union all
select 333,456 union all
select 444,88

select [tel],[other] from(
select COUNT(*)over(partition by [tel]) as counts,* from test)a
where counts>=2
/*
tel other
111 33
111 11
333 456
333 44
444 55
444 88
*/

#9


首先我先说一下我说说的那个“虚拟表d”,代码如下

select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
from(
            select * from
               (     
                 select * from (select * from Orders) a 
                               full join (select * from PatientCome) b 
                               on a.GUID = b.ComeGUID
               ) c
               where (c.ProjectID=16 or RealProjectID=16)
                  and 
                 (
                   (convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') 
                   or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02') 
                 )
     ) d



现在我在真实数据中测试一下 Tel值为1381122334在“表d”*出现在多少行中 代码改写如下

select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
from(
            select * from
               (     
                 select * from (select * from Orders) a 
                               full join (select * from PatientCome) b 
                               on a.GUID = b.ComeGUID
               ) c
               where (c.ProjectID=16 or RealProjectID=16)
                  and 
                 (
                   (convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') 
                   or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02') 
                 )
     ) d
    where Tel ='1381122334'


运行结果是,只在一行中出现过,换句话说 Tel值为1381122334在“表d”中只在一行中出现过 。

接下来我整理一下发帖的那条sql语句,为了直观。可以简化成如下

WITH CTE AS (
 --表d)
SELECT * FROM CTE A
WHERE A.Tel <>'' and EXISTS (
SELECT 1 FROM CTE WHERE Tel = A.Tel AND RowID <> A.RowID) order by Tel

好了 ,记下来运行一下上面的简化代码, 结果,本不应该出现的1381122334所在行居然出现在了查询结果中。当然,得到的数据大部分结果都是正确的(也就是却是tel重复的数据都查出来了),几百条数据,也就是有那么仅有的几条出现了这种情况。

#10


引用 6 楼  的回复:
感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果 

比如表d的数据如下
HTML code

 tel      other
  111     11
  222      22
  111     33
  333     44
 ……


不要遇到问题就用CTE,找重复的完全可以避免CTE

#11


好了 我已经把整理好的需求和问题阐述清楚了,感谢楼上给出的测试代码以及建议,
但本人sql属于初学水平阶段,所以更希望高手能在我的代码基础上改一改,当然 我会尝试将测试代码理解并加在自己的sql中,但水平有限会花费很久时间 还未必能成功。。。

#12


引用 10 楼  的回复:
引用 6 楼 的回复:

感谢楼上,第一个问题已经解决了(也就是tel字段为空的字段不算差重范围)。
现在要解决第二个问题,也是非常头痛的问题。

为了便于大家更容易的分析我的问题,我先用一个demo来模拟一下我想要的结果

比如表d的数据如下
HTML code

tel other
111 11
222 22
111 33
333 44
……

不要遇到问……

感谢你的测试代码,我已经写出来可以查询出正确结果的sql

select * from(
                select COUNT(*)over(partition by Tel) as counts,* from 
                 (
                           select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
                           from(
                                  select * from
                                  (      
                                   select * from (select * from Orders) a 
                                   full join (select * from PatientCome) b 
                                   on a.GUID = b.ComeGUID
                                  ) c
                                  where (c.ProjectID=16 or RealProjectID=16)
                                  and 
                                  ((convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02'))
                               ) d
                 ) w
             ) a
where counts>=2 and (Tel is not null) and Tel<>''

#13


你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

#14


引用 13 楼  的回复:
你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

根据你的代码 我已经写出了可以查询出正确结果的sql语句了

select * from(
                select COUNT(*)over(partition by Tel) as counts,* from 
                 (
                           select RowID = ROW_NUMBER() OVER (ORDER BY (case when Time is null then TimeC else Time end) ASC,NEWID()),* 
                           from(
                                  select * from
                                  (      
                                   select * from (select * from Orders) a 
                                   full join (select * from PatientCome) b 
                                   on a.GUID = b.ComeGUID
                                  ) c
                                  where (c.ProjectID=16 or RealProjectID=16)
                                  and 
                                  ((convert(varchar(10),Time,120) >= '2010-01-01' and convert(varchar(10),Time,120) <='2015-02-02') or (convert(varchar(10),TimeC,120) >= '2010-01-01' and convert(varchar(10),TimeC,120) <='2015-02-02'))
                               ) d
                 ) w
             ) a
where counts>=2 and (Tel is not null) and Tel<>N''

#15


引用 14 楼  的回复:
引用 13 楼  的回复:
你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

根据你的代码 我已经写出了可以查询出正确结果的sql语句了
SQL code

select * from(
                select COUNT(*)over(partition by Tel) as counts,* from 
……


恭喜。看代码看得头晕,所以说直接给测试数据最好。而且大家把握住你的意思也会很准确

#16


引用 15 楼  的回复:
引用 14 楼 的回复:

引用 13 楼 的回复:
你就给原始代码吧。不要你上面的语句。然后你再给出对应的结果。这样大家看的更清楚,更准确的把握住你的需求

根据你的代码 我已经写出了可以查询出正确结果的sql语句了
SQL code

select * from(
select COUNT(*)over(partition by Tel) as counts,* from
……

呵呵 感谢你的帮助!!!好开心解决了这个问题!!!