如何将表中的一列记录转换成栏头(行),另一列记录转换成栏头下对应的记录(行),##数据表列转换成行?(100分)

  • 主题发起人 主题发起人 war_cryer
  • 开始时间 开始时间
W

war_cryer

Unregistered / Unconfirmed
GUEST, unregistred user!
A表结构如下:<br> 姓名 部门 工资项 值 <br> 张三 A部  底薪 1000<br> 张三 A部  补贴 200<br> 张三 A部  奖金 1000<br> 李四 B部  提成 1200<br> 李四 B部  底薪 1000<br> 李四 B部  补贴 200<br> 李四 B部  奖金 1000<br><br>通过SQL 实现要求如下:<br> 姓名 部门 底薪   补贴     奖金    提成<br> 张三 A部 1000  200   1000  0<br> 李四 B部 1000  200   1000  1200<br><br> 请问此SQL如何实现,谢谢!<br> 
 
DECLARE @Temp nvarchar(4000)<br>DECLARE @Sql nvarchar(4000)<br>set @Temp=N''<br>DECLARE Employee_Cursor CURSOR FOR<br>--SELECT item_name FROM t_item<br>select item_name from t_Item where item_name in(<br>select &nbsp;name from syscolumns where id=object_id('t_City'))<br>OPEN Employee_Cursor<br>FETCH NEXT FROM Employee_Cursor INTO @AA<br>WHILE @@FETCH_STATUS = 0<br>BEGIN<br>&nbsp; &nbsp;IF @Temp = N'' <br>BEGIN<br>&nbsp; &nbsp; &nbsp; &nbsp; Set @Temp = N'SELECT &nbsp;'+ rtrim(@AA)<br>&nbsp; &nbsp; &nbsp; &nbsp; END<br>&nbsp; &nbsp;ELSE<br>&nbsp; &nbsp; &nbsp; &nbsp; BEGIN<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set @Temp = @Temp +N','+ rtrim(@AA)<br>&nbsp; &nbsp; &nbsp; &nbsp; END<br>&nbsp; &nbsp;FETCH NEXT FROM Employee_Cursor INTO @AA<br>END<br>Set @Temp = &nbsp;rtrim(@Temp) + N' &nbsp;FROM t_city'<br><br>Print @Temp<br><br>EXEC sp_executesql &nbsp;@Temp <br><br><br>CLOSE Employee_Cursor<br>DEALLOCATE Employee_Cursor<br><br><br><br><br><br><br><br><br><br>=============================<br>--行列转换 行转列<br>DROP TABLE t_change_lc;<br>CREATE TABLE t_change_lc (card_code VARCHAR2(3), q NUMBER, bal NUMBER);<br><br>INSERT INTO t_change_lc <br>SELECT 001 card_code, ROWNUM q, trunc(dbms_random.VALUE * 100) bal FROM dual CONNECT BY <br><br>ROWNUM &lt;= 4<br>UNION <br>SELECT 002 card_code, ROWNUM q, trunc(dbms_random.VALUE * 100) bal FROM dual CONNECT BY <br><br>ROWNUM &lt;= 4;<br><br>SELECT * FROM t_change_lc;<br><br>SELECT a.card_code,<br>SUM(decode(a.q, 1, a.bal, 0)) q1,<br>SUM(decode(a.q, 2, a.bal, 0)) q2,<br>SUM(decode(a.q, 3, a.bal, 0)) q3,<br>SUM(decode(a.q, 4, a.bal, 0)) q4<br>FROM t_change_lc a<br>GROUP BY a.card_code<br>ORDER BY 1;<br><br>--行列转换 列转行<br>DROP TABLE t_change_cl;<br>CREATE TABLE t_change_cl AS <br>SELECT a.card_code,<br>SUM(decode(a.q, 1, a.bal, 0)) q1,<br>SUM(decode(a.q, 2, a.bal, 0)) q2,<br>SUM(decode(a.q, 3, a.bal, 0)) q3,<br>SUM(decode(a.q, 4, a.bal, 0)) q4<br>FROM t_change_lc a<br>GROUP BY a.card_code<br>ORDER BY 1;<br><br>SELECT * FROM t_change_cl;<br><br>SELECT t.card_code,<br>t.rn q,<br>decode(t.rn, 1, t.q1, 2, t.q2, 3, t.q3, 4, t.q4) bal<br>FROM (SELECT a.*, b.rn<br>FROM t_change_cl a,<br>(SELECT ROWNUM rn FROM dual CONNECT BY ROWNUM &lt;= 4) b) t<br>ORDER BY 1, 2;<br><br>--行列转换 行转列 合并<br>DROP TABLE t_change_lc_comma;<br>CREATE TABLE t_change_lc_comma AS SELECT card_code,quarter_||q AS q FROM t_change_lc; <br><br>SELECT * FROM t_change_lc_comma;<br><br>SELECT t1.card_code, substr(MAX(sys_connect_by_path(t1.q, ;)), 2) q<br>FROM (SELECT a.card_code,<br>a.q,<br>row_number() over(PARTITION BY a.card_code ORDER BY a.q) rn<br>FROM t_change_lc_comma a) t1<br>START WITH t1.rn = 1<br>CONNECT BY t1.card_code = PRIOR t1.card_code<br>AND t1.rn - 1 = PRIOR t1.rn<br>GROUP BY t1.card_code;<br><br>--行列转换 列转行 分割<br>DROP TABLE t_change_cl_comma;<br>CREATE TABLE t_change_cl_comma AS<br>SELECT t1.card_code, substr(MAX(sys_connect_by_path(t1.q, ;)), 2) q<br>FROM (SELECT a.card_code,<br>a.q,<br>row_number() over(PARTITION BY a.card_code ORDER BY a.q) rn<br>FROM t_change_lc_comma a) t1<br>START WITH t1.rn = 1<br>CONNECT BY t1.card_code = PRIOR t1.card_code<br>AND t1.rn - 1 = PRIOR t1.rn<br>GROUP BY t1.card_code;<br><br>SELECT * FROM t_change_cl_comma;<br><br>SELECT t.card_code,<br>substr(t.q,<br>instr(; || t.q, ;, 1, rn),<br>instr(t.q || ;, ;, 1, rn) - instr(; || t.q, ;, 1, rn)) q<br>FROM (SELECT a.card_code, a.q, b.rn<br>FROM t_change_cl_comma a,<br>(SELECT ROWNUM rn FROM dual CONNECT BY ROWNUM &lt;= 100) b<br>WHERE instr(; || a.q, ;, 1, rn) &gt; 0) t<br>ORDER BY 1, 2;
 
select distinct(姓名), 部门,<br>&nbsp; (select 值 from testTable t2 where t2.姓名=t1.姓名 and 工资项='底薪')as "底薪",<br>&nbsp; (select 值 from testTable t2 where t2.姓名=t1.姓名 and 工资项='补贴')as "补贴",<br>&nbsp; (select 值 from testTable t2 where t2.姓名=t1.姓名 and 工资项='奖金')as "奖金",<br>&nbsp; (select 值 from testTable t2 where t2.姓名=t1.姓名 and 工资项='提成')as "提成"<br>&nbsp;from testTable t1
 
啊,怎么这么多人这东西啊<br><br>才上来就看到两个贴子,给你个通用的<br><br><br>if &nbsp;exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CrossTable]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)<br>drop proceudre<br><br>alter PROCEDURE CrossTable --交叉表生成器<br>--(Select Distinct SuppCode As SCode,MCode,PurQtyRate As Rate<br>-- &nbsp; &nbsp; &nbsp; &nbsp;From MtSPM A Inner Join MtSPD B On A.ID=B.MtSuppPriceM_ID<br>-- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Inner Join Suppliers C On A.Supp_ID=C.ID<br>-- &nbsp; &nbsp; &nbsp; &nbsp;Where A.Active_KID=120 And AduitPass=1) D<br>@vSourceTAB As Varchar(2000), --数据来源表,可以为表,视图,或者SQL语句(要用括号以及别名:如上注释段)<br>@vGroupbyField As Varchar(100), --被selct Group By 要显示出来的,可以多个字段(记录可以有空值)<br>@vTransFormCol As Varchar(50), --交叉表中的合计等函数计算值的字段<br>@vFunction As Varchar(100)=' Sum', --默认值,交叉表中的函数,也可以是' 2*Sum'的计算公式<br>@vPivotCol As Varchar(100), --要转换成列的字段,唯一列,可以是表达式'Field1+Field2'(记录可以有空值)<br>@vStrWhere As Varchar(1000) =Null, --Where 约束条件,可以为空<br>@vGroupbyFieldName As Varchar(50)=null --如果GroupField是表达式,则这里一定要指定名称,不然会出错<br>AS<br>--重要提示:@StrSql的Largest size allowed Is 8000,因此尽量将少的字段内容转换为列<br>Declare @StrSql As Varchar(8000) --//总的SQL语句<br>Declare @StrSum As Varchar(3000) --//列合计<br>Declare @pCols As Varchar(100)<br>Declare @StrWhere As Varchar(500)<br><br>if @vGroupbyFieldName is null<br>set @vGroupbyFieldName=@vGroupbyField<br><br>set @strsql=' Declare CursorCross Cursor For &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Select Distinct ' + @vPivotCol + ' From ' +@vSourceTAB +' Order By ' + @vPivotCol + ' For Read only '<br>Print @StrSql<br>Execute(@StrSql)<br>Begin<br>&nbsp; Set Nocount On<br>&nbsp; Set @StrSql =''<br>&nbsp; Set @StrSum=''<br>&nbsp; Set @pCols=''<br>&nbsp; IF Rtrim(Ltrim(IsNull(@vStrWhere,''))) &lt;&gt; ''<br>&nbsp; Begin<br>&nbsp; &nbsp; Set @StrWhere=' Where ' + @vStrWhere + ' '<br>&nbsp; End<br>Else<br>&nbsp; Set @StrWhere=''<br>&nbsp; Open CursorCross<br>&nbsp; While (0=0)<br>&nbsp; Begin<br>&nbsp; &nbsp; Fetch Next From CursorCross Into @pCols<br>&nbsp; &nbsp; IF (@@Fetch_Status&lt;&gt;0) Break<br>&nbsp; &nbsp; IF @pCols Is &nbsp;Null --//不为空值,<br>&nbsp; &nbsp; Set @pCols='Null'<br>&nbsp; &nbsp; --为了防止新创建的列的标题名称,与@vGroupbyField中的字段重名,<br>&nbsp; &nbsp; --新创建的列的标题名称都增加前缀[@vGroupbyField.新创建的列的标题名称]<br>--因Sql长度限制Max=8000,由源数据控制字段值不能为Null,因此这里不再检验值是否为Null<br>&nbsp; &nbsp; Set @StrSql=@StrSql +',' + @vFunction +<br>&nbsp; &nbsp; &nbsp; &nbsp; '(Case '+@vPivotCol+' When ''' + @pCols+ ''' Then '+@vTransFormCol +' Else Null End) As '+ <br>&nbsp; &nbsp; &nbsp; &nbsp; '['+/*Left(@vPivotCol,1)+*/@pCols+']'<br>--因长度限制,不计算列间之和<br>-- &nbsp; &nbsp;Set @StrSum=@StrSum + '+IsNull(A.' + '['+Left(@vPivotCol,1)+@pCols+']' +',0)'<br>&nbsp; End<br>&nbsp; Set &nbsp;@StrSql = ' Select ' + @vGroupByField +' AS '+@vGroupbyFieldName+ ' ' +@StrSql + ' From ' +@vSourceTAB+ ' ' + @StrWhere +<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;' Group By ' + @vGroupByField <br>&nbsp; --列向合计 为字段名'TotalSum',合计方法改为重新从源表中取值,减少SQL的字符量<br>&nbsp; Set @StrSql ='Select A.*,(select '+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@vFunction+'(' +@vTransFormCol +') from '+ @vSourceTAB+@StrWhere+' Group by '+@vGroupbyField+ ' having '+@vGroupbyField+'=A.'+@vGroupbyFieldName<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+') As TotalSum From (' + @StrSql &nbsp;+') As A'<br>&nbsp; Set @StrSql ='Select A.* into #CrossTable From ('+@StrSql+') As A &nbsp;Order By '+@vGroupByFieldName<br>&nbsp; Print @StrSql<br>&nbsp; Execute(@StrSql)<br>&nbsp; IF @@Error &lt;&gt;0<br>&nbsp; &nbsp; Return @@Error<br>&nbsp; Close CursorCross<br>&nbsp; Deallocate CursorCross<br>&nbsp; Return 0<br>End<br><br>go
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
843
import
I
S
回复
0
查看
928
SUNSTONE的Delphi笔记
S
后退
顶部