在T-SQL中按自定义功能分组

时间:2015-05-21 21:41:31

标签: sql-server tsql sql-server-2008-r2 group-by

我有一张人员表,其中可能有重复。我的目标是返回可能重复的列表,以便我们可以将它们组合成一个新人。

我希望明确地按first_namelast_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子句中添加一些内容来比较出生日期。

2 个答案:

答案 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