关于数据库列转行的问题。

兰色与白色 2014-02-12 04:03:54
SQL SERVER 2005以后列转行有个函数可以直接用。
2000的数据库我当初做的时候用的是
select 日期,
max(case id when '列头A' then 值 end ) as 列头A,
max(case id when '列头B' then 值 end ) as 列头B,
max(case id when '列头C' then 值 end ) as 列头C,
max(case id when '列头D' then 值 end ) as 列头D
FROM (SELECT 日期,列头(包含ABCD),值 from table ) t1 group by thisd



SELECT 日期,列头(包含ABCD),值 from table
的查询结果是这样的
日期 列头 值
20140101 A 100
20140101 B 100
20140101 C 100
20140102 A 100
20140102 B 100
20140102 C 100
20140103 A 100
20140103 B 100
20140103 C 100

我想知道这里的MAX到底是什么用处啊。。
除了因为配合GROUP BY 要用聚合包起来。
那换成MIN之类的不是一样效果么?
...全文
368 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
xusir98 2014-02-14
  • 打赏
  • 举报
回复
兰色与白色 2014-02-13
  • 打赏
  • 举报
回复
根据28楼的原理。 找了公司DB。解释了半小时好像有些明白了。。 不过自己还是解释不出。不过脑子里通了。。这是悟道了么0 0 谢谢大家。。
唐诗三百首 2014-02-12
  • 打赏
  • 举报
回复
因为产生动态SQL时是逐行拼接出来的. 如下例子.

declare @y varchar(20)

;with t as
(select 'a' 'x' union all
 select 'b' 'x' union all
 select 'c' 'x' union all
 select 'd' 'x')
select @y=isnull(@y,'')+x from t

select @y 'y'

/*
y
--------------------
abcd

(1 row(s) affected)
*/
兰色与白色 2014-02-12
  • 打赏
  • 举报
回复
引用 24 楼 ap0405140 的回复:
[quote=引用 22 楼 chi4419424 的回复:] 对啊。。我知道结果是会出现N个when then 语句。 也知道它的表头是根据。数据库distinct来的。 问题是中间的循环生成是怎么出来的。。。 是一个特定的语法?表达式?
用动态SQL实现,找个SQL2000的行列转换例子看看就明白了.[/quote] 看了 迷糊了啊。。。 效果是能实现。 但是不知道过程。 见我25楼说明。 也不知道我有木有说清楚。。
發糞塗牆 2014-02-12
  • 打赏
  • 举报
回复
这样把,你把测试数据改成一个A,看看print出来的,然后改成A,B,再平ring出来,这个本人解释能力有限,我也不知道怎么解释,不过我个人的理解它不是循环。只是有点像对号入座的意思吧
兰色与白色 2014-02-12
  • 打赏
  • 举报
回复
引用 23 楼 DBA_Huangzj 的回复:
根据我的理解,预期说是“循环”,还不如说是匹配,在一列中,通过case when,判断是否符合某个值,如果复合就取数,否则就0
你说的是case when then end 的原理。。 我说的是 根据那个动态语句 它没有明显的循环判断。 一条语句是怎么会自动转换成 和我的N个when then 一样的效果。 就相当于如过是在程序里。不在SQL 中。 string title={'A','B','C','D','E','F'}//数组定义= =很少用不知道是不是这样 string sql="select"; string whenThen=""; for(int i=0;i<title.length;i++){ whenThen=whenThen+"sum(case when 列头='"+title[i]+"' then 值 else 0 end) as "'+title[i]+"','"; } sql=sql+whenThen; 程序里是这样动态生成的。 sql里我没发现它是怎么生成的。。。
唐诗三百首 2014-02-12
  • 打赏
  • 举报
回复
引用 22 楼 chi4419424 的回复:
对啊。。我知道结果是会出现N个when then 语句。 也知道它的表头是根据。数据库distinct来的。 问题是中间的循环生成是怎么出来的。。。 是一个特定的语法?表达式?
用动态SQL实现,找个SQL2000的行列转换例子看看就明白了.
發糞塗牆 2014-02-12
  • 打赏
  • 举报
回复
根据我的理解,预期说是“循环”,还不如说是匹配,在一列中,通过case when,判断是否符合某个值,如果复合就取数,否则就0
兰色与白色 2014-02-12
  • 打赏
  • 举报
回复
引用 21 楼 DBA_Huangzj 的回复:
把exec改成print
对啊。。我知道结果是会出现N个when then 语句。 也知道它的表头是根据。数据库distinct来的。 问题是中间的循环生成是怎么出来的。。。 是一个特定的语法?表达式?
發糞塗牆 2014-02-12
  • 打赏
  • 举报
回复
把exec改成print
兰色与白色 2014-02-12
  • 打赏
  • 举报
回复
引用 16 楼 DBA_Huangzj 的回复:
如果列头是固定的,没必要搞动态,不过动态也是可以的
引用 5 楼 zlp321002 的回复:
比如,你可以类似这么写,求sum; declare @sql varchar(2000) set @sql='select ,' select @sql=@sql+'sum(case when 列头='''+列头+''' then 值 else 0 end) as '+列头+',' from ( select distinct 列头 from 表名 )tb set @sql=substring(@sql,1,len(@sql)-1) set @sql=@sql+' from 表名 group by 日期 '
我看不懂这里是怎么自动循环动态生成动态的那个语句的。 然后我搜索了相关信息。 发现别人也是这个问题发生了很长的讨论。 链接这里 http://bbs.csdn.net/topics/300121913 发现 sum(case when 列头='''+列头+''' then 值 else 0 end) as '+列头+',' from ( select distinct 列头 from 表名 )tb 这里面会自动根据数据库里有N个列头生成 N个 WHEN THEN 的枚举。 看了上面的帖子我只理解这里会自动生成。 至于原因和里面原理还是不明白。 能拆分解释下么。。。比如那里的3个' ' '这种情况。也是不明白的一个原因。
發糞塗牆 2014-02-12
  • 打赏
  • 举报
回复
引用 17 楼 sqlkxr 的回复:
[quote=引用 1 楼 DBA_Huangzj 的回复:] 其实你那个查询应该是case when xx then 值 else null end 这样,而null比那个“值”小,所以用max,如果换min,就会显示null出来
大哥,你也不能胡说啊。在聚合函数中null值都是被忽略的。用min出来的也不是null(只要有一个非null),是最小值。如果一个null和一个1,出来的min绝对是1[/quote]这个是说错了,null不会出来
zlp321002 2014-02-12
  • 打赏
  • 举报
回复
引用 14 楼 chi4419424 的回复:
[quote=引用 5 楼 zlp321002 的回复:] 比如,你可以类似这么写,求sum; declare @sql varchar(2000) set @sql='select ,' select @sql=@sql+'sum(case when 列头='''+列头+''' then 值 else 0 end) as '+列头+',' from ( select distinct 列头 from 表名 )tb set @sql=substring(@sql,1,len(@sql)-1) set @sql=@sql+' from 表名 group by 日期 '
这个是动态的sql? 我当初没用是因为没想到怎么把每个列头循环,A,B,C,D,E加入到 CASE WHEN 里面。。 你这个好像也没这个功能啊。 [/quote] 我这有这个功能,你自己用表测试下,就是动态加的表头;
sqlkxr 2014-02-12
  • 打赏
  • 举报
回复
引用 1 楼 DBA_Huangzj 的回复:
其实你那个查询应该是case when xx then 值 else null end 这样,而null比那个“值”小,所以用max,如果换min,就会显示null出来
大哥,你也不能胡说啊。在聚合函数中null值都是被忽略的。用min出来的也不是null(只要有一个非null),是最小值。如果一个null和一个1,出来的min绝对是1
發糞塗牆 2014-02-12
  • 打赏
  • 举报
回复
如果列头是固定的,没必要搞动态,不过动态也是可以的
兰色与白色 2014-02-12
  • 打赏
  • 举报
回复
引用 13 楼 DBA_Huangzj 的回复:
如果为了不抱错,SUM/MAX/MIN/AVG这些都可以,不过出来的结果可能不是你想要的
嗯。明白了。这个因不同业务需求使用。而纯粹的转换没有其他业务需求的情况下。任意都可以。只是为了聚合。
兰色与白色 2014-02-12
  • 打赏
  • 举报
回复
引用 5 楼 zlp321002 的回复:
比如,你可以类似这么写,求sum; declare @sql varchar(2000) set @sql='select ,' select @sql=@sql+'sum(case when 列头='''+列头+''' then 值 else 0 end) as '+列头+',' from ( select distinct 列头 from 表名 )tb set @sql=substring(@sql,1,len(@sql)-1) set @sql=@sql+' from 表名 group by 日期 '
这个是动态的sql? 我当初没用是因为没想到怎么把每个列头循环,A,B,C,D,E加入到 CASE WHEN 里面。。 你这个好像也没这个功能啊。
發糞塗牆 2014-02-12
  • 打赏
  • 举报
回复
如果为了不抱错,SUM/MAX/MIN/AVG这些都可以,不过出来的结果可能不是你想要的
發糞塗牆 2014-02-12
  • 打赏
  • 举报
回复
是否用sum、max、min要看业务需求,没有强制要求
LongRui888 2014-02-12
  • 打赏
  • 举报
回复
引用 10 楼 chi4419424 的回复:
[quote=引用 8 楼 DBA_Huangzj 的回复:] 用了group by,所有未包含在聚合函数中的列都要在group by中出现,因为行转列的过程一般会有多条数据,而我们把“不符合”行转列的数据强制为null或者0,再用max,就可以取出我们要的数据了
奥,那还是就是说如果不是为了其他特殊要求。 比如 20140101 A 100 20140101 A 300 这种情况因为有2条数据列转行因为一个列头只有一个对应的值所以要用到SUM。 其他我的情况就只是为了聚合而使用啊= =没有其他的意义。是我想复杂了啊。[/quote] 嗯 对的,其他的情况,就是为了用聚合函数,没有其他的意思,而上面的按个得用sum来求和。
加载更多回复(10)

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧