如何将多行合并为一行,其中行值不同

时间:2011-12-23 09:44:58

标签: sql sql-server

如何使用SQL Server获取单行,其中唯一的非空值是通过所有选定行保持一致且非空的值。

 A    B     C     D
10   NULL  text  NULL
4    abc   text  NULL
4    def   text  NULL

应该给出以下一行:

 A    B     C     D
NULL NULL  text  NULL

3 个答案:

答案 0 :(得分:4)

create table #t (col1 int, col2 char(3), col3 char(4), col4 int)
go
insert into #t select 10, null, 'text', null
insert into #t select 4, 'abc', 'text', null
insert into #t select 4, 'def', 'text', null
go

select 
    case when count(distinct isnull(col1, 0)) > 1 then null else max(col1) end as 'col1',
    case when count(distinct isnull(col2, '')) > 1 then null else max(col2) end as 'col2',
    case when count(distinct isnull(col3, '')) > 1 then null else max(col3) end as 'col3',
    case when count(distinct isnull(col4, 0)) > 1 then null else max(col4) end as 'col4'
from 
    #t
go

drop table #t
go

编辑:我添加了ISNULL来处理t-clausen.dk识别的问题但这只有在'默认'值(即零和空字符串)没有出现在真实中时才会起作用数据

Daniel关于数据类型的评论也是正确的,但由于我们不知道所涉及的数据类型,因此建议替代方案并不容易。提供使用真实数据类型的自包含测试脚本是提出这样的问题的最佳方式。

答案 1 :(得分:3)

declare @t table(A int, b varchar(10), c varchar(max), d int)

insert @t values(10, null, 'text', null)
insert @t values(4, 'abc', 'text', null)
insert @t values(10, 'def', 'text', null)


select case when max(rna) > 1 then null else min(a) end, 
case when max(rnb) > 1 then null else min(b) end, 
case when max(rnc) > 1 then null else min(c) end, 
case when max(rnd) > 1 then null else min(d) end 
 from 
(
select rna = rank() over(order by a),
rnb = rank() over(order by b),
rnc = rank() over(order by c),
rnd = rank() over(order by d),
a, b,c,d
 from @t
 ) e

如果您有文本列,请使用varchar(max)替换列类型。文本列已过时。

首先考虑使用count(distinct col1),但它不计算空值。

select count(distinct a) from (select cast(null as int) a) b 

返回0行

答案 2 :(得分:2)

SELECT 
    CASE WHEN  COUNT(DISTINCT col1) = 1
           AND COUNT(col1) = COUNT(*) 
         THEN MIN(col1)
    END AS col1
  , CASE WHEN  COUNT(DISTINCT col2) = 1 
           AND COUNT(col2) = COUNT(*)
         THEN MIN(col2)
    END AS col2
  , CASE WHEN  COUNT(DISTINCT col3) = 1 
           AND COUNT(col3) = COUNT(*)
         THEN MIN(col3)
    END AS col3
  , CASE WHEN  COUNT(DISTINCT col4) = 1 
           AND COUNT(col4) = COUNT(*)
         THEN MIN(col4)
    END AS col4
FROM
    tableX