我还是刚从事数据库工作,所以请耐心等待。我已经阅读了许多类似的问题,但似乎没有人谈论我面临的同样问题。
关于我正在做什么的一些信息,我有一个填充了联系信息的表,并且有些联系人是重复的,但是大多数重复的行都有一个截断的电话号码,这使得这些数据无用。
我编写了以下查询来搜索重复项:
$h = fopen('/var/www/whatever/rates.txt', 'w');
fwrite($h, print_r($rates, true));
fclose($h);
我认为此查询会根据我指定的三列找到所有重复记录,并选择WITH CTE (CID, Firstname, lastname, phone, email, length, dupcnt) AS
(
SELECT
CID, Firstname, lastname, phone, email, LEN(phone) AS length,
ROW_NUMBER() OVER (PARTITION BY Firstname, lastname, email
ORDER BY Firstname) AS dupcnt
FROM
[data.com_raw]
)
SELECT *
FROM CTE
WHERE dupcnt > 1
AND length <= 10
大于1的任何记录,以及长度小于或等于的电话列等于10.但是当我不止一次运行查询时,每次执行都会得到不同的结果集。必须有一些我在这里缺少的逻辑,但我完全被这个困惑了。所有列都是dupcnt
数据类型,但CID除外,它是varchar
。
答案 0 :(得分:2)
而不是ROW_NUMBER()
使用COUNT(*)
,并删除ORDER BY,因为COUNT(*)
不需要这样做。
现在,您可以按firstname
/ lastname
/ email
将记录分组到类似的记录组/分区中。然后,您按firstname
对每个组/分区进行排序。 Firstname
是分区的一部分,意味着该组/分区中的每个名字都是相同的。您将获得不同的结果,具体取决于SQL Server从存储中获取结果的方式(首先找到的记录是1
,第二个找到的记录是2
)。每次获取记录(每次运行此sql)时,它都可以从磁盘或缓存中以不同的顺序获取每条记录。
Count(*)
将返回所有重复的行
所以相反:
COUNT(*) OVER (PARTITION BY Firstname, lastname, email ) AS dupcnt
这将返回共享相同名字,姓氏和电子邮件的记录数。然后保留任何大于1的记录。
答案 1 :(得分:0)
ORDER BY Firstname
在这里是不确定的,因为它们都具有来自分区的相同名字
如果CID是唯一的,你可以使用它作为订单,但我怀疑你真的想要数。
答案 2 :(得分:0)
我相信每次运行都会得到不同的结果,因为(a)除非在查询中明确指定,否则您不能假设SQL在查询中返回数据的顺序,以及(b)唯一的排序标准你提供的是FirstName,它远不如你的分组(名字,姓氏,电子邮件)精确。
对于查询本身,如所写,它假定在给定分区中找到的第一个项目包含有效的电话号码。如果没有指定订单,您就无法知道这是真的......如果给定分组中的所有商品都有无效的电话号码怎么办?以下是我希望以有用的格式提取您正在寻找的数据。
WITH CTE -- Sorry, I'm lazy and generally don't list the columns
AS
(
SELECT
Firstname
,lastname
,phone
,count(*) HowMany -- How many in group
,sum(case len(phone) when 10 then 1 else 0 end) BadLength -- How many "bad" in group
from data.com_raw
group by
Firstname
,lastname
,phone
having count(*) <> sum(case len(phone) when 10 then 1 else 0 end)
and count(*) > 1 -- Remove this to find singletons with invalid phone numbers
)
select
cr.CID
,cr.Firstname
,cr.lastname
,case len(cr.phone) when 10 then '' else 'Bad' end) IsBad
,cr.phone
,cr.email
from data.com_raw cr
inner join CTE
on CTE.Firstname = cr.Firstname
and CTE.lastname = cr.lastname
and CTE.phone = cr.phone
order by
cr.CID
,cr.Firstname
,cr.lastname
,case len(cr.phone) when 10 then '' else 'Bad' end)
,cr.phone
(是的,如果没有索引支持这一点,您将最终进行表扫描。)
答案 3 :(得分:-1)
SELECT Firstname, lastname,email, COUNT(*)
FROM [data.com_raw]
GROUP BY Firstname, lastname,email HAVING COUNT(*)>1
WHERE LEN(PHONE)<= 10