SQL Distinct处理多列的问题

  今天在做SSIS的ETL工作时,其中一个left join组件的运行结果总是会多出一些记录。分析了一下,该问题的原因是右表中作为关联的那一列数据有重复。left join的运行策略可以理解为根据左表的每一条记录的关联字段去对照右表的关联字段,如果右表的关联字段存在重复,就会生成重复的记录。如果左表存在重复而右表无重复,则不会多出来记录。举个例子,如果左表a和右表b的数据分别如下所示

a表
ID Name
1 张三
2 李四
3 王五
4 王陆
b表
ID Description
1 内联部
1 系学生会
2 外联部
3 团委

  这时如果用ID作为关联字段用a表left join b表,结果会产生5条记录,比左表多一条。(顺便提一下,如果右表不重复,则left join的结果数会与左表相等)

a表left join b表结果
ID Name Description
1 张三 内联部
1 张三 系学生会
2 李四 外联部
3 王五 团委
4 王陆 NULL

 

 

 

 

 

 

 

  实际上,我想要的结果是与左表a一一对应,不要有重复的记录。这可以通过SSIS的lookup组件实现,但是效率会很低。因此就想到把右表中的重复记录去除掉再join两张表。首先自然地想到用distinct函数去重

SELECT DISTINCT ID, Description
FROM      B

  结果却是1条记录都没去掉,因为Distinct是作用于多列的,也就是说必须要ID和Description全都相同的才会被剔除。

  在网上搜了一下,有人说用 select *, count(distinct name) from table group by name  这样的语句是可行的,但我在SQL Server里面试了一下会报错。只好自己动手,丰衣足食啦,想了一下,其实可以用下面的语句

SELECT   ID,  Max(Description) AS Description
FROM      B
GROUP BY ID

   进一步的思考后发现,SQL Server中有First_Value和Last_Value函数,也可以实现

SELECT    DISTINCT ID,    FIRST_VALUE(Description) OVER (PARTITION BY ID 
                 ORDER BY Description) AS Description FROM B

  第二种方法中Partition by的参数必须是ID,Order by的参数可以调整,这就使得该方法更加灵活。这两种方法经实测效率差不多,第一种稍微快一点点。不过遗憾的是SSIS中不支持第二种方法,只能用第一种group by的方式。

 

posted @ 2014-11-06 19:31  斜行闲作草  阅读(49754)  评论(1编辑  收藏  举报