我有一张人员表,其中可能有重复。我的目标是返回可能重复的列表,以便我们可以将它们组合成一个新人。
我希望明确地按first_name
和last_name
进行分组。但是,如果两个人的记录都有一个已定义的birth_date
并且这些日期不同,那么我想要排除这些记录,因为赔率是人们不同但恰好具有相同的名称。
另一个警告是,在我们的系统中(我继承了),birth_date
列为NOT NULL
,未指定的birth_date
设置为'1900-01-01'
。
我有没有办法GROUP BY
自定义函数(或使用其他一些聪明的逻辑),它只比较birth_date
列检查两者是否都不是默认日期,或者它们是否为相同,或者接受参数,比如说每个person_id
并将记录相互比较,返回BIT
来决定它们是否应该算作同一个组?
我想避免使用CLR定义的聚合函数(因为我对它没有经验)。
到目前为止(没有birth_date
比较)我的查询是:
SELECT *
FROM core_person P
WHERE last_name + ',' + first_name IN
(SELECT last_name + ',' + first_name "name"
FROM core_person
GROUP BY last_name + ',' + first_name
HAVING COUNT(*) > 1)
ORDER BY last_name + ',' + first_name
我想在GROUP BY
子句中添加一些内容来比较出生日期。
答案 0 :(得分:1)
如果日期等于1/1/1900为nullif(Birthday,'1/1/1900')
,则可以使用nullif函数返回空值。
此查询可让您开始查看所有可能匹配的记录:
select p1.person_id
from core_person p1
join core_person p2
on p1.person_id <> p2.person_id
and LEFT(p1.first_name,5) = LEFT(p2.first_name,5)
and LEFT(p1.last_name,5) = LEFT(p2.last_name,5)
and isnull(nullif(p1.Birthday,'1/1/1900'), p2.Birthday) = isnull(nullif(p2.Birthday,'1/1/1900'), p1.Birthday)
group by p1.person_id
如果生日中的任何一个等于1/1/1900,它会将生日与自身进行比较,否则它只会在两个记录中等同于生日。
如果您不想查看匹配项,可以使用上述查询的变体作为子查询,仅返回重复的ID值:
select core_person
from core_person
where person_id in
(
select p1.person_id
from core_person p1
join core_person p2
on p1.person_id <> p2.person_id
and LEFT(p1.first_name,5) = LEFT(p2.first_name,5)
and LEFT(p1.last_name,5) = LEFT(p2.last_name,5)
and isnull(nullif(p1.Birthday,'1/1/1900'), p2.Birthday) = isnull(nullif(p2.Birthday,'1/1/1900'), p1.Birthday)
group by p1.person_id
)
答案 1 :(得分:0)
而不是分组,这样的事情会对你有用吗?
select * from MyTable a
left join MyTable b
on a.person_id < b.person_id
and a.first_name = b.first_name
and a.last_name = b.last_name
and (
a.birthdate = b.birthdate
or a.birthdate = '1900-1-1'
or b.birthdate = '1900-1-1'
)
它匹配姓氏和名字匹配的行,并且生日匹配或一个生日是您的占位符值。联接的person_ID部分摆脱了重复(例如,1匹配到2,然后另一行,其中2匹配为1,或1匹配为1)。
您可能希望扩大名称的匹配条件以查看前几个字符或使用SOUNDEX
,但是您的匹配可能需要更多手动排序作为最后一步。
编辑:要返回表格中可能有重复且与其匹配无关的所有记录的列表,请改用:
select distinct a.* from MyTable a
inner join MyTable b
on a.person_id <> b.person_id
and a.first_name = b.first_name
and a.last_name = b.last_name
and (
a.birthdate = b.birthdate
or a.birthdate = '1900-1-1'
or b.birthdate = '1900-1-1'
)
order by a.first_name, a.last_name, a.birthdate