Quantcast
Viewing latest article 1
Browse Latest Browse All 2

能否实现行转列(Pivot),并且合并列?

有如下形式的表mytable2:

ID    TYPE   SUBTYPE    COUNT   MONTH
 1      A      Z          1       7/1/2008
 1      A      Z          3       7/1/2008
 2      B      C          2       7/2/2008
 1      A      Z          3       7/2/2008

我能否用SQL查询得到如下的输出:

ID    A_Z   B_C   MONTH
1     4     0     7/1/2008
2     0     2     7/2/2008
1     0     3     7/2/2008

这样,TYPE和SUBTYPE合并成新的列,而COUNT列根据ID,MONTH分组求和。

注意:这里假设我们有100多这样的TYPES和SUBTYPES,所以如果在SQL中硬编码A和Z可能并不是非常有效。这样的SQL如何实现呢?这里RDBMS为SQLServer。

本题来源stackoverflow

本题第一眼看的时候,我们能想到用case when来实现行转列以及求和的需求,但是由于TYPES和SUBTYPES数量大,我们可以试试SQLServer 2005的Pivot,当然依然需要拼接动态SQL。具体如下:
/*声明三个字符变量,都用于保存拼接出的字符串结果*/
declare @sql as varchar(max)
declare @pivot_list as varchar(max) -- leave null for coalesce technique
declare @select_list as varchar(max) -- leave null for coalesce technique

/*加号+实现concat拼接字符串的功能;coalesce处理null*/
select @pivot_list = coalesce(@pivot_list + ', ', '') + '[' + pivot_code + ']'
    	,@select_list = coalesce(@select_list + ', ', '') + 'isnull([' + pivot_code + '], 0) as [' + pivot_code + ']'
from (
    select distinct concat(type, '_', subtype) as pivot_code
    from mytable2
) as pivot_codes

set @sql = '
;with p as (
    select id, [month], [type] + ''_'' + subtype as pivot_code, sum([count]) as [count]
    from mytable2
    group by id, [month], [type] + ''_'' + subtype
)
select id, [month], '' + @select_list + ''
from p
pivot (
    sum([count])
    for pivot_code in (
    	'' + @pivot_list + ''
    )
) as pvt
'

/*执行生成的动态SQL*/
exec (@sql)

上述方法,首先使用子查询表pivot_codes找出所有不同的合并列,并利用其生成拼接字符串。然后利用pivot进行行转列的操作和sum操作。

由于语句动态生成,其实也可以类似上述方式拼接成case when语句,但是相较pivot的使用比较笨拙,在其他RDBMS下可以考虑尝试。

The post 能否实现行转列(Pivot),并且合并列? appeared first on SQLParty.


Viewing latest article 1
Browse Latest Browse All 2

Trending Articles