产品价格等级表
等级 价格 型号
5 100.00 200116
4 99.00 0010
4 99.00 0012
4 99.00 0013
4 3.00 0031
1 1.00 0001
8 888.00 3222
3 333.00 3222
要求
1.型号对应有不同等级,不同等级价格可以定不同价格。现在要求按型号来分组,显示这个型号的所有等级与所有价格。
2.只要数据库定了某个型号,所有的型号都有这一列(列是动态的)
结果
fPId level1 level3 level4 level5 level8
0010 NULL NULL 99.00 NULL NULL
0012 NULL NULL 99.00 NULL NULL
0013 NULL NULL 99.00 NULL NULL
0031 NULL NULL 3.00 NULL NULL
200116 NULL NULL NULL 100.00 NULL
3222 NULL 333.00 NULL NULL 888.00
代码最比较少,但却花了我不少时间,感谢csdn的各位帮助了,行转列,原来数据库的操作我懂得真的是太少了。。。
第一步。先直接分析行转列的结果表达式,要什么样的SQL语句才能得到这样的结果呢?
select
fPId,
max(case fPPLevel when '1' then fPPPrices else null end) [level1],
max(case fPPLevel when '3' then fPPPrices else null end) [level3],
max(case fPPLevel when '4' then fPPPrices else null end) [level4],
max(case fPPLevel when '5' then fPPPrices else null end) [level5],
max(case fPPLevel when '8' then fPPPrices else null end) [level8],
from vProPriceLevel
group by fPId
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
第二步,可以看出这样的表达式是没有规律的,如果真的要将比如说1-10等级,全部在里case表达式里列出,那就不是动态列,成静态了。
如果客户要求增加等级,或者不显示不需要的等级呢?要转成动态,没办法另外想办法了
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
declare @sql varchar(6000)
set @sql = 'select fPId,'
select @sql = @sql +' max(case 等级 when '''+ cast(等级 as varchar(20))+''' then 价格 else null end) [level'+cast(等级 as varchar(20))+'],'
from (select distinct 等级 from 产品价格等级表) tmp
set @sql = substring(@sql, 1, len(@sql)-1) +' from 产品价格等级表'
print @sql
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
第三步,上面的输出结果正好是我们想要的 sql语句,动态的语句只能用存储过程去实现了.行转列到这里已经完成了,相信后面的操作大家都会.最终项目需要的不只这么简单,
添加了按样本多选与按产品型号(产品名)模糊查询的要求.再加上分页,并返回总记录数,最终形式如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
/***************************************************************
名称:spProPriceLevel
功能:产品价格等级 行转列,支持分页,筛选
exec [spProPriceLevel]
@proid '',
@fSName '',
@start 0,
@limit 50
***************************************************************/
alter proc [dbo].[spProPriceLevel]
@proid varchar(20),
@fSName varchar(20), --其实是样本的编号,用","连起来的
@start int = 0,
@limit int = 50
as
declare @sql varchar(6000)
set @sql = 'select ROW_NUMBER() OVER(Order By fPId) as SysRowNum,fSName,fSId,fPId,'
select @sql = @sql +' sum(case fPPLevel when '''+ cast(fPPLevel as varchar(20))+''' then fPPPrices else null end) [level'+cast(fPPLevel as varchar(20))+'],'
from (select distinct fPPLevel as fPPLevel from dbo.tbPPrices) tmp
set @sql = substring(@sql, 1, len(@sql)-1) +' from vProPriceLevel'
set @sql=@sql+' where fPId like '''+@proid+'%''';
if(@fSName!='')
set @sql=@sql+' and fSId in ('+@fSName+')';
/*设定排序语句.*/
DECLARE @strStartRow varchar(50),@strEndRow varchar(50)
/*默认当前页*/
IF @start < 0
SET @start = 0
/*设置分页参数.*/
SET @strStartRow = CAST((@start + 1) AS varchar(50))
SET @strEndRow = CAST((@start + @limit) AS varchar(50))
/*执行查询语句*/
set @sql ='select * from ('+
@sql + 'group by fSName,fPId,fSId) as v where SysRowNum between '+@strStartRow+' and '+@strEndRow
set @sql = @sql + ';select count(distinct(fPId)) from vProPriceLevel'
if(@fSName!='')
set @sql=@sql+' where fSId in ('+@fSName+')';
exec (@sql)
print (@Sql)