昨天被一從前同事問及sql2K中交叉表的使用﹐回顧了一下sql﹐現根據QQ聊天記錄整理了一下﹐順便征求各位一個超過varchar型最大值8000后該如何實現的動態sql語句。
建立測試環境﹕
create table #t (id_date datetime,order_f varchar(20),qty numeric(18,0))
insert into #t select id_date=case when (day(id_date)<>1) then dateadd(day,-day(id_date)+1, id_date)
else id_date
end
,order_f, qty from ODBC_TEST
declare @s varchar(8000)
set @s='select ID_Date '
select @s=@s+','+Order_F+'=sum(case when Order_F='''+Order_F+''' then QTY else 0 end)'
from #t
group by Order_F
set @s=@s+' from #t group by ID_Date order by ID_Date desc '
--print cast(len(@s) as varchar)
exec(@s)
drop table #t
結果如下﹕
當然使用以上的動態SQL語句﹐如果數據過多﹐串聯起來的字符超過了8K,就會出錯的﹐曾記得CSDN上鄒健還是誰﹐有發表過如何解決這個超過8K字符的文章﹐可惜我現在沒有找到﹐如果哪位有找到﹐或有解決方法﹐請不吝賜教﹗先謝了﹗
建立測試環境﹕
CREATE TABLE [ODBC_TEST] (
[ID_Date] [datetime] NULL ,
[Order_F] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
[QTY] [numeric](18, 0) NULL
) ON [PRIMARY]
GO
insert into odbc_test
select '2006-12-01','aa',10
union all
select '2006-12-02','bb',20
union all
select '2006-12-03','cc',30
union all
select '2007-01-01','aa',10
union all
select '2007-01-02','bb',20
union all
select '2007-01-03','cc',30
--select * from ODBC_TEST
他要的就是按年月分Oder_F統計QTY。當時我正在開緊電影﹐給出了第一個方案﹕[ID_Date] [datetime] NULL ,
[Order_F] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,
[QTY] [numeric](18, 0) NULL
) ON [PRIMARY]
GO
insert into odbc_test
select '2006-12-01','aa',10
union all
select '2006-12-02','bb',20
union all
select '2006-12-03','cc',30
union all
select '2007-01-01','aa',10
union all
select '2007-01-02','bb',20
union all
select '2007-01-03','cc',30
--select * from ODBC_TEST
declare @s varchar(8000)
set @s='select ID_Date '
select @s=@s+','+Order_F+'=sum(case when Order_F='''+Order_F+''' then QTY else 0 end)'
from ODBC_TEST
group by Order_F
set @s=@s+' from ODBC_TEST group by ID_Date order by ID_Date desc '
--print cast(len(@s) as varchar)
exec(@s)
結果﹕set @s='select ID_Date '
select @s=@s+','+Order_F+'=sum(case when Order_F='''+Order_F+''' then QTY else 0 end)'
from ODBC_TEST
group by Order_F
set @s=@s+' from ODBC_TEST group by ID_Date order by ID_Date desc '
--print cast(len(@s) as varchar)
exec(@s)
ID_Date aa bb cc
------------------------------------------------------ ---------------------------------------- ---------------------------------------- ----------------------------------------
2007-01-03 00:00:00.000 0 0 30
2007-01-02 00:00:00.000 0 20 0
2007-01-01 00:00:00.000 10 0 0
2006-12-03 00:00:00.000 0 0 30
2006-12-02 00:00:00.000 0 20 0
2006-12-01 00:00:00.000 10 0 0
并沒有分年月﹐只是按日分而已﹐知道并沒有實現他的要求﹐在自已電腦中寫出了一個方案二﹕------------------------------------------------------ ---------------------------------------- ---------------------------------------- ----------------------------------------
2007-01-03 00:00:00.000 0 0 30
2007-01-02 00:00:00.000 0 20 0
2007-01-01 00:00:00.000 10 0 0
2006-12-03 00:00:00.000 0 0 30
2006-12-02 00:00:00.000 0 20 0
2006-12-01 00:00:00.000 10 0 0
create table #t (id_date datetime,order_f varchar(20),qty numeric(18,0))
insert into #t select id_date=case when (day(id_date)<>1) then dateadd(day,-day(id_date)+1, id_date)
else id_date
end
,order_f, qty from ODBC_TEST
declare @s varchar(8000)
set @s='select ID_Date '
select @s=@s+','+Order_F+'=sum(case when Order_F='''+Order_F+''' then QTY else 0 end)'
from #t
group by Order_F
set @s=@s+' from #t group by ID_Date order by ID_Date desc '
--print cast(len(@s) as varchar)
exec(@s)
drop table #t
ID_Date aa bb cc
------------------------------------------------------ ---------------------------------------- ---------------------------------------- ----------------------------------------
2007-01-01 00:00:00.000 10 20 30
2006-12-01 00:00:00.000 10 20 30
感覺怪怪的﹐并沒有達到預期想要的顯示效果﹐所以﹐我當時要他多等一會兒時間﹐這個時候﹐該從前同事發過來了他的方案代碼﹕------------------------------------------------------ ---------------------------------------- ---------------------------------------- ----------------------------------------
2007-01-01 00:00:00.000 10 20 30
2006-12-01 00:00:00.000 10 20 30
declare @s varchar(8000)
set @s='select Order_f, '
select @s=@s+'sum(case left(convert(varchar(10),id_date,120),7) when '''+id_date+''' then qty else 0 end) as '''+ id_date+''','
from
(select distinct left(convert(varchar(10),id_date,120),7) as id_date from odbc_test ) a
set @s = left(@s,len(@s)-1) +'from odbc_test group by order_f order by order_f'
exec(@s)
運行結果﹕set @s='select Order_f, '
select @s=@s+'sum(case left(convert(varchar(10),id_date,120),7) when '''+id_date+''' then qty else 0 end) as '''+ id_date+''','
from
(select distinct left(convert(varchar(10),id_date,120),7) as id_date from odbc_test ) a
set @s = left(@s,len(@s)-1) +'from odbc_test group by order_f order by order_f'
exec(@s)
Order_f 2006-12 2007-01
-------------------- ---------------------------------------- ----------------------------------------
aa 10 10
bb 20 20
cc 30 30
faint....真有點暈﹐看來以后使用sql還是要從多方面著想﹐說不定什么時間就有靈感﹐使出不一樣而且簡潔輕便的實現方法﹐比傳統的思維要好很多。就比如說這個﹐唉﹐為什么不想一下日期型轉成字符型﹐然后取7位不就是年月了嗎?再次faint...-------------------- ---------------------------------------- ----------------------------------------
aa 10 10
bb 20 20
cc 30 30
當然使用以上的動態SQL語句﹐如果數據過多﹐串聯起來的字符超過了8K,就會出錯的﹐曾記得CSDN上鄒健還是誰﹐有發表過如何解決這個超過8K字符的文章﹐可惜我現在沒有找到﹐如果哪位有找到﹐或有解決方法﹐請不吝賜教﹗先謝了﹗