表结构如下:
表A:
name string
date datetime
07:00 bool
08:00 bool
表数据:
name date 07:00 08:00 09:00 10:00 11:00 12:00
gm 2012-06-20 1 0 1 0 1 0
gm 2012-06-11 1 0 1 0 0 0
求教:
按照每个time时间的bool值,只取true,如何让查询结果转变成为:name date time
gm 2012-06-20 07:00
gm 2012-06-20 09:00
gm 2012-06-20 11:00
gm 2012-06-11 07:00
gm 2012-06-11 09:00
这样做是否可行?请教大家。
表A:
name string
date datetime
07:00 bool
08:00 bool
表数据:
name date 07:00 08:00 09:00 10:00 11:00 12:00
gm 2012-06-20 1 0 1 0 1 0
gm 2012-06-11 1 0 1 0 0 0
求教:
按照每个time时间的bool值,只取true,如何让查询结果转变成为:name date time
gm 2012-06-20 07:00
gm 2012-06-20 09:00
gm 2012-06-20 11:00
gm 2012-06-11 07:00
gm 2012-06-11 09:00
这样做是否可行?请教大家。
--> 测试数据:[test]
if object_id('[test]') is not null
drop table [test]
create table [test](
[name] varchar(2),
[date] datetime,
[07:00] int,
[08:00] int,
[09:00] int,
[10:00] int,
[11:00] int,
[12:00] int
)
go
insert [test]
select 'gm','2012-06-20',1,0,1,0,1,0 union all
select 'gm','2012-06-11',1,0,1,0,0,0
go
declare @s nvarchar(4000)
select @s=isnull(@s+' union all ','')+'select [name],[date],[time]
='+quotename(Name,'''')
+',[value]='+quotename(Name)+' from test'
from syscolumns where ID=object_id('test')
and Name not in('name','date')
order by Colid
exec('select name,convert(varchar(10),date,120) as date,time from(
select * from ('+@s+')t )m where value=1 order by [name],[date]')
/*
name date time
--------------------------------------
gm 2012-06-11 07:00
gm 2012-06-11 09:00
gm 2012-06-20 11:00
gm 2012-06-20 09:00
gm 2012-06-20 07:00
*/
表1:
ID Name Date
1 gm 2012-06-11
表2:
ID ID表1 Time
1 1 07:00
2 1 09:00然后用
select * from 表1
inner join 表2 ...对于数据库来说,数据结构非常重要,一般情况下要尽可能避免表结构的变化,不然后期的开发就是噩梦。对于你原先的结构,如果只需要对于某一天添加新的时间,你不光要添加新列,而且还要定义每一行(每个)的值,空间不说,也麻烦很多。
如果定义成两个表,你只需要在表2中添加一行数据就行。表结构根本就不用动。
请问我建了哪两个表??
我只是利用了系统表而已,你的表结构怎么变不影响这个语句这就是行列转换问题,目前的解决方法就是这些:--行列互转
--摘自中国风博客,引用请标明内容来源
--1、行换列
if object_id('Class') is not null
drop table Class
Go
Create table Class(
[Student] nvarchar(2),
[Course] nvarchar(2),
[Score] int)
Insert Class
select N'张三',N'语文',78 union all
select N'张三',N'数学',87 union all
select N'张三',N'英语',82 union all
select N'张三',N'物理',90 union all
select N'李四',N'语文',65 union all
select N'李四',N'数学',77 union all
select N'李四',N'英语',65 union all
select N'李四',N'物理',85
Go--2000方法:
--动态:
declare @s nvarchar(4000)
set @s=''
Select @s=@s+','+quotename([Course])+'=max(case when [Course]='
+quotename([Course],'''')+' then [Score] else 0 end)'
from
Class group by[Course]
--select @s
exec('select [Student]'+@s+' from Class group by [Student]')
--生成静态:
select
[Student],
[数学]=max(case when [Course]='数学' then [Score] else 0 end),
[物理]=max(case when [Course]='物理' then [Score] else 0 end),
[英语]=max(case when [Course]='英语' then [Score] else 0 end),
[语文]=max(case when [Course]='语文' then [Score] else 0 end)
from
Class
group by [Student]
GO
--动态:declare @s nvarchar(4000)
Select @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course]
select @s
exec('select * from Class pivot (max([Score]) for [Course] in('+@s+'))b')--生成静态:
select *
from
Class
pivot
(max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b--生成格式:
/*
Student 数学 物理 英语 语文
------- ----------- ----------- ----------- -----------
李四 77 85 65 65
张三 87 90 82 78(2 行受影响)
*/go
--加上总成绩(学科平均分)--2000方法:
--动态:declare @s nvarchar(4000)
set @s=''
Select @s=@s+','+quotename([Course])+'=max(case when [Course]='+quotename([Course],'''')+'then [Score] else 0 end)'
from Class group by[Course]
exec('select [Student]'+@s+',[总成绩]=sum([Score]) from Class group by [Student]')--加多一列(学科平均分用avg([Score]))生成动态:select
[Student],
[数学]=max(case when [Course]='数学' then [Score] else 0 end),
[物理]=max(case when [Course]='物理' then [Score] else 0 end),
[英语]=max(case when [Course]='英语' then [Score] else 0 end),
[语文]=max(case when [Course]='语文' then [Score] else 0 end),
[总成绩]=([Score]) --加多一列(学科平均分用avg([Score]))
from
Class
group by [Student]go--2005方法:动态:declare @s nvarchar(4000)
Select @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course]
--isnull(@s+',','') 去掉字符串@s中第一个逗号exec('select [Student],'+@s+',[总成绩] from (select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a
pivot (max([Score]) for [Course] in('+@s+'))b ')--生成静态:select
[Student],[数学],[物理],[英语],[语文],[总成绩]
from
(select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a --平均分时用avg([Score])
pivot
(max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b 生成格式:/*
Student 数学 物理 英语 语文 总成绩
------- ----------- ----------- ----------- ----------- -----------
李四 77 85 65 65 292
张三 87 90 82 78 337(2 行受影响)
*/go--2、列转行
if not object_id('Class') is null
drop table Class
Go
Create table Class([Student] nvarchar(2),[数学] int,[物理] int,[英语] int,[语文] int)
Insert Class
select N'李四',77,85,65,65 union all
select N'张三',87,90,82,78
Go--2000:动态:declare @s nvarchar(4000)
select @s=isnull(@s+' union all ','')+'select [Student],[Course]='+quotename(Name,'''')--isnull(@s+' union all ','') 去掉字符串@s中第一个union all
+',[Score]='+quotename(Name)+' from Class'
from syscolumns where ID=object_id('Class') and Name not in('Student')--排除不转换的列
order by Colid
exec('select * from ('+@s+')t order by [Student],[Course]')--增加一个排序生成静态:
select *
from (select [Student],[Course]='数学',[Score]=[数学] from Class union all
select [Student],[Course]='物理',[Score]=[物理] from Class union all
select [Student],[Course]='英语',[Score]=[英语] from Class union all
select [Student],[Course]='语文',[Score]=[语文] from Class)t
order by [Student],[Course]go
--2005:动态:declare @s nvarchar(4000)
select @s=isnull(@s+',','')+quotename(Name)
from syscolumns where ID=object_id('Class') and Name not in('Student')
order by Colid
exec('select Student,[Course],[Score] from Class unpivot ([Score] for [Course] in('+@s+'))b')go
select
Student,[Course],[Score]
from
Class
unpivot
([Score] for [Course] in([数学],[物理],[英语],[语文]))b
生成格式:
/*
Student Course Score
------- ------- -----------
李四 数学 77
李四 物理 85
李四 英语 65
李四 语文 65
张三 数学 87
张三 物理 90
张三 英语 82
张三 语文 78
*/
if object_id('[test]') is not null
drop table [test]
create table [test](
[name] varchar(2),
[date] datetime,
[07:00] int,
[08:00] int,
[09:00] int,
[10:00] int,
[11:00] int,
[12:00] int
)
go
insert [test]
select 'gm','2012-06-20',1,0,1,0,1,0 union all
select 'gm','2012-06-11',1,0,1,0,0,0
gowith col as (
select sc.name
from syscolumns sc,sysobjects s where sc.id=s.id and s.name='test' and sc.name<>'name' and sc.name<>'date'
)
select t.name,t.date,c.name as [time]
from col c,[test] t
where (case when( c.[name]='07:00' and t.[07:00]=0 )then 0
when( c.[name]='08:00' and t.[08:00]=0 )then 0
when( c.[name]='09:00' and t.[09:00]=0 )then 0
when( c.[name]='10:00' and t.[10:00]=0 )then 0
when( c.[name]='11:00' and t.[11:00]=0 )then 0
when( c.[name]='12:00' and t.[12:00]=0 )then 0
else 1 end )=1 group by t.name,t.date,c.name
gm 2012-06-11 00:00:00.000 07:00
gm 2012-06-11 00:00:00.000 09:00
gm 2012-06-20 00:00:00.000 07:00
gm 2012-06-20 00:00:00.000 09:00
gm 2012-06-20 00:00:00.000 11:00
select name from syscolumns where ID=object_id('test') and name<>'name' and name<>'date'
)
select t.name,t.date,c.name as [time]
from col c,[test] t
where (case when( c.[name]='07:00' and t.[07:00]=0 )then 0
when( c.[name]='08:00' and t.[08:00]=0 )then 0
when( c.[name]='09:00' and t.[09:00]=0 )then 0
when( c.[name]='10:00' and t.[10:00]=0 )then 0
when( c.[name]='11:00' and t.[11:00]=0 )then 0
when( c.[name]='12:00' and t.[12:00]=0 )then 0
else 1 end )=1
改进了下。