假设有张学生成绩表(tb)如下:

Name Subject Result

张三 语文  74

张三 数学  83

张三 物理  93

李四 语文  74

李四 数学  84

李四 物理  94

想变成

姓名         语文        数学        物理

李四         74          84          94

张三         74          83          93

*/

create table tb

( Name    varchar(10) , Subject varchar(10) , Result  int

)

insert into tb(Name , Subject , Result) values('张三' , '语文' , 74)

insert into tb(Name , Subject , Result) values('张三' , '数学' , 83)

insert into tb(Name , Subject , Result) values('张三' , '物理' , 93)

insert into tb(Name , Subject , Result) values('李四' , '语文' , 74)

insert into tb(Name , Subject , Result) values('李四' , '数学' , 84)

insert into tb(Name , Subject , Result) values('李四' , '物理' , 94)

go

--静态SQL,指subject只有语文、数学、物理这三门课程。

select name 姓名,

max(case subject when '语文' then result else 0 end) 语文,

max(case subject when '数学' then result else 0 end) 数学,

max(case subject when '物理' then result else 0 end) 物理

from tb

group by name

/*

姓名         语文        数学        物理

李四         74          84          94

张三         74          83          93

*/

--动态SQL,指subject不止语文、数学、物理这三门课程。

declare @sql varchar(8000)

set @sql = 'select Name as ' + '姓名'

select @sql = @sql + ' , max(case Subject when ''' + Subject + ''' then Result else 0 end) [' + Subject + ']'

from (select distinct Subject from tb) as a

set @sql = @sql + ' from tb group by name'

exec(@sql)

/*

姓名         数学        物理        语文

李四         84          94          74

张三         83          93          74

*/

/*加个平均分,总分

姓名         语文        数学        物理        平均分                总分

李四         74          84          94          84.00                252

张三         74          83          93          83.33                250

*/

--静态SQL,指subject只有语文、数学、物理这三门课程。

select name 姓名,

max(case subject when '语文' then result else 0 end) 语文,

max(case subject when '数学' then result else 0 end) 数学,

max(case subject when '物理' then result else 0 end) 物理,

cast(avg(result*1.0) as decimal(18,2)) 平均分,

sum(result) 总分

from tb

group by name

/*

姓名         语文        数学        物理        平均分                总分

李四         74          84          94          84.00                252

张三         74          83          93          83.33                250

*/

--动态SQL,指subject不止语文、数学、物理这三门课程。

declare @sql1 varchar(8000)

set @sql1 = 'select Name as ' + '姓名'

select @sql1 = @sql1 + ' , max(case Subject when ''' + Subject + ''' then Result else 0 end) [' + Subject + ']'

from (select distinct Subject from tb) as a

set @sql1 = @sql1 + ' , cast(avg(result*1.0) as decimal(18,2)) 平均分,sum(result) 总分 from tb group by name'

exec(@sql1)

/*

姓名         数学        物理        语文        平均分                总分

李四         84          94          74          84.00                252

张三         83          93          74          83.33                250

*/

drop table tb

/*

如果上述两表互相换一下:即

姓名 语文 数学 物理

张三 74  83  93

李四 74  84  94

想变成

Name       Subject Result

李四         语文      74

李四         数学      84

李四         物理      94

张三         语文      74

张三         数学      83

张三         物理      93

*/

create table tb1

( 姓名 varchar(10) ,   语文 int ,   数学 int ,   物理 int)

insert into tb1(姓名 , 语文 , 数学 , 物理) values('张三',74,83,93)

insert into tb1(姓名 , 语文 , 数学 , 物理) values('李四',74,84,94)

select * from

(

select 姓名 as Name , Subject = '语文' , Result = 语文 from tb1

union all

select 姓名 as Name , Subject = '数学' , Result = 数学 from tb1

union all

select 姓名 as Name , Subject = '物理' , Result = 物理 from tb1

) t

order by name , case Subject when '语文' then 1 when '数学' then 2 when '物理' then 3 when '总分' then 4 end

/*加个平均分,总分

Name       Subject     Result

李四         语文      74.00

李四         数学      84.00

李四         物理      94.00

李四         平均分    84.00

李四         总分      252.00

张三         语文      74.00

张三         数学      83.00

张三         物理      93.00

张三         平均分    83.33

张三         总分      250.00

*/

select * from

(

select 姓名 as Name , Subject = '语文' , Result = 语文 from tb1

union all

select 姓名 as Name , Subject = '数学' , Result = 数学 from tb1

union all

select 姓名 as Name , Subject = '物理' , Result = 物理 from tb1

union all

select 姓名 as Name , Subject = '平均分' , Result = cast((语文 + 数学 + 物理)*1.0/3 as decimal(18,2)) from tb1

union all

select 姓名 as Name , Subject = '总分' , Result = 语文 + 数学 + 物理 from tb1

) t

order by name , case Subject when '语文' then 1 when '数学' then 2 when '物理' then 3 when '平均分' then 4 when '总分' then 5 end

CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,

Emp3 int, Emp4 int, Emp5 int);

GO

INSERT INTO pvt VALUES (1,4,3,5,4,4);

INSERT INTO pvt VALUES (2,4,1,5,5,5);

INSERT INTO pvt VALUES (3,4,3,5,4,4);

INSERT INTO pvt VALUES (4,4,2,5,5,4);

INSERT INTO pvt VALUES (5,5,1,5,5,5);

GO

-------------------------------------------

SELECT VendorID, Employee, Orders

FROM

(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5

FROM pvt) p

UNPIVOT

(Orders FOR Employee IN

(Emp1, Emp2, Emp3, Emp4, Emp5)

)AS unpvt;

GO

=================================================================================================================

1. 用一条SQL语句 查询出每门课都大于80分的学生姓名

name   kecheng    fenshu

张三     语文     81

张三     数学     75

李四     语文     76

李四     数学     90

王五     语文     81

王五     数学     100

王五     英语     90

思路:这里不能直接用 分数>80这样的比较条件来查询的到结果,因为要求没门成绩都大于80。我们可以反过来思考,如果有一门成绩小于80,那么就不符合要求。先找出成绩表中成绩<80的多有学生姓名,不能重复,然后再用not in找出不再这个集合中的学生姓名。

create table #成绩(姓名varchar(20),课程名称varchar(20),分数int)

insert into #成绩values

('张三',     '语文',       81),

('张三',     '数学',       75),

('李四',     '语文',       76),

('李四',     '数学',       90),

('王五',     '语文',      81),

('王五',     '数学',       100),

('王五',     '英语',       90)

select distinct(姓名) from #成绩 where 姓名 not in(select distinct(姓名) from #成绩 where 分数<=80)

经luofer提示还有一种思路,是用group by + hvaing,这绝对是一种好方法。我估计出这个题的人就是要考察这个知识,代码如下:

select 姓名 from #成绩

group by 姓名

having min(分数)>80

还有一种方法类似于第一种

select distinct a.姓名 from #成绩 a where not exists (select 1 from #成绩 where 分数<80 and 姓名=a.姓名)

2. 学生表 如下:

自动编号   学号   姓名  课程编号  课程名称  分数

1      2005001 张三  0001   数学    69

2      2005002 李四  0001   数学    89

3      2005001 张三 0001   数学    69

删除除了自动编号不同,其他都相同的学生冗余信息

思路:这个和上面的一样,也不能直接删除,而是要先找出自动编号不相同,其他都相同的行,这个要使用group by语句,并且将其他的字段都放在group by后面,这样找出来的行都是没有冗余的行,然后随便保留其中一个自动编号,删除其他的行。

create table #成绩(自动编号 int, 学号 int,姓名 varchar(20),课程编号 int,课程名称 varchar(20),分数 int)

insert into #成绩 values

(1,2005001 ,'张三',  1,   '语文',       81),

(2,2005001 ,'李四',  1,   '语文',       81),

(3,2005001 ,'张三',  1,   '语文',       81),

(4,2005001 ,'张三',  1,   '语文',       81)

select * from #成绩

drop table #成绩

delete from #成绩 where 自动编号 not in

(select MIN(自动编号) from #成绩 group by 学号,姓名,课程编号,课程名称,分数)

经广岛之恋的提醒发现另外一种思路,代码如下:

delete from #成绩 where 自动编号 not in

(select distinct(a.自动编号) from #成绩 a join #成绩 b on a.自动编号>b.自动编号

where a.学号=b.学号 and a.姓名=b.姓名 and a.课程编号=b.课程编号 and a.分数=b.分数)

如果不考虑自动编号,还可以这样

--注意identity用法,只能用在有into的select语句中

select identity(int,1,1) as id, 学号,姓名,课程编号,课程名称,分数

into #temp

from #成绩 group by 学号,姓名,课程编号,课程名称,分数

truncate table #成绩

insert into #成绩 select * from #temp

3. 一个叫department的表,里面只有一个字段name,一共有4条纪录,分别是a,b,c,d,对应四个球对,现在四个球对进行比赛,用一条sql语句显示所有可能的比赛组合。

思路:这是一个组合问题,就是说四个不同的元素有多少种不同的两两组合。现在要把这个问题用sql语句实现。既然这四个元素是不相同的,我们可以将这个表当成两个集合,求他们的笛卡尔积,然后再从笛卡尔积中找到那些元素不相同的,并且不重复的组合。

create table #department(taname char(1))

insert into #department values

('a'),('b'),('c'),('d')

--下面两条语句都可以,多谢wanglinglong提醒

select a.taname,b.taname from #department a,#department b where a.taname < b.taname

select a.taname,b.taname from #department a,#department b where a.taname > b.taname

4.怎么把这样一个表

year  month amount

1991   1     1.1

1991   2     1.2

1991   3     1.3

1991   4     1.4

1992   1     2.1

1992   2     2.2

1992   3     2.3

1992   4     2.4

查成这样一个结果

year  m1  m2  m3  m4

1991  1.1   1.2   1.3   1.4

1992  2.1   2.2   2.3   2.4

思路:这个很明显是一个行列转换,首先会想到pivot。结果中有m1,m2,m3,m4四个新的列,他们需要从原来的行中转换。

create table #sales(years int,months int,amount float)

insert into #sales values

(1991,   1,     1.1),

(1991,   2,     1.2),

(1991,   3,     1.3),

(1991,   4,     1.4),

(1992,   1,     2.1),

(1992,   2,     2.2),

(1992,   3,     2.3),

(1992,   4,     2.4)

select pt.years,[1] as m1,[2] as m2,[3] as m3,[4] as m4

from (select sod.amount,sod.months,sod.years as years from  #sales sod)  so

pivot

(min(so.amount) for so.months in ([1], [2],[3],[4])) as pt

注意[1],[2],[3],[4]中括号不可缺少,否则会出错。还有一种写法是使用子查询,这个要新建4个子查询进而得到新的列:

select a.years,

(select m.amount from #sales m where months=1 and m.years=a.years) as m1,

(select m.amount from #sales m where months=2 and m.years=a.years) as m2,

(select m.amount from #sales m where months=3 and m.years=a.years) as m3,

(select m.amount from #sales m where months=4 and m.years=a.years) as m4

from #sales a group by a.years

还可以这样写,大同小异:

select  a.years,

sum(case months when 1 then amount else 0 end) as m1,

sum(case months when 2 then amount else 0 end) as m2,

sum(case months when 3 then amount else 0 end) as m3,

sum(case months when 4 then amount else 0 end) as m4

from #sales a group by a.years

5.有两个表A和B,均有key和value两个字段,如果B的key在A中也有,就把B的value换为A中对应的value。这道题的SQL语句怎么写?

思路:这个问题看似简单,只要一个update语句,然后找到相同的key,更新value字段就可以了。可能你首先会写成这样:update #b set #b.value=(select #a.value from #a where #a.keys=#b.keys)。但是要注意的是如果仅仅找相同的key会有很多匹配,更新的时候会出现错误,所以要在外层限制。

create table #a(keys int , value varchar(10))

insert into #a values

(1,'aa'),

(2,'ab'),

(3,'ac')

create table #b(keys int , value varchar(10))

insert into #b values

(1,'aa'),

(2,'a'),

(3,'a')

update #b set #b.value=(select #a.value from #a where #a.keys=#b.keys) where #b.keys in

(select #b.keys from #b,#a where #a.keys=#b.keys and #a.value<>#b.value)

在luofer的提醒之,有了第二个思路

update #b set #b.value=s.value

from (select * from #a except select * from #b) s where s.keys=#b.keys

luofer是牛人啊!

6. 两张关联表,删除主表中已经在副表中没有的信息。

思路:这个就是存在关系,可以使用in,也可以使用exists。

create table #zhubiao(id int,name varchar(5))

insert into #zhubiao values

(1,'aa'),

(2,'ab'),

(3,'ac')

create table #fubiao(id int, grade varchar(5))

insert into #fubiao values

(1,'aa'),

(2,'ab')

delete from #zhubiao where id not in(select b.id from #fubiao b)

delete from #zhubiao where not exists(select 1 from #fubiao where #zhubiao.id=#fubiao.id)

7. 原表:

courseid coursename score

1   java          70

2      oracle       90

3      xml            40

4      jsp             30

5      servlet     80

为了便于阅读,查询此表后的结果显式如下(及格分数为60):

courseid coursename score mark

1        java         70  pass

2        oracle     90  pass

3        xml          40  fail

4         jsp          30  fail

5    servlet    80     pass

思路:这个就很直接了,使用case语句判断一下。

create table #scores(course int,coursename varchar(10),score int)

insert into #scores values

(1, 'java', 70 ),

(2, 'oracle', 90),

(3, 'xmls', 40),

(4, 'jsp', 30),

(5, 'servlet', 80 )

select course,coursename,

case when score>60 then 'pass' else 'fail' end as mark

from #scores

8. 原表:

id proid proname

1 1 M

1 2 F

2 1 N

2 2 G

3 1 B

3 2 A

查询后的表:

id pro1 pro2

1 M F

2 N G

3 B A

思路:依旧是行列转换,这个在面试中的几率很高。这个语句还是有两种写法,如下:

create table #table1(id int,proid int,proname char)

insert into #table1 values

(1, 1, 'M'),

(1, 2, 'F'),

(2, 1, 'N'),

(2, 2, 'G'),

(3, 1, 'B'),

(3, 2, 'A')

select id,

(select proname from #table1 where proid=1 and id=b.id) as pro1,

(select proname from #table1 where proid=2 and id=b.id) as pro2

from #table1 b group by id

select d.id,[1] as pro1,[2] as pro2 from

(select b.id,b.proid,b.proname from #table1 b) as c

pivot

(min(c.proname) for c.proid in([1],[2])) as d

9. 如下

表a

列    a1 a2

记录  1  a

1  b

2  x

2  y

2  z

用select能选成以下结果吗?

1 ab

2 xyz

思路:这个开始想使用行列转换来写,没有成功,后来没有办法只好用游标,代码如下:

create table #table2(id int , value varchar(10))

insert into #table2 values

(1,'a'),

(1,'b'),

(2,'x'),

(2,'y'),

(2,'z')

create table #table3(id int,value varchar(100) );insert into #table3(id,value) select distinct(id),'' from #table2

declare @id int,@name varchar(10)

declare mycursor cursor for select * from #table2

open mycursor

fetch next from mycursor into @id,@name

while (@@Fetch_Status = 0)

begin

update #table3 set value=value+@name where id=@id

fetch next from mycursor into @id,@name

end

close mycursor

deallocate mycursor

select * from #table3

有两个要注意的地方,

a.#table3里面的value字段初始值如果不设置的话默认是null,后面更新的时候null+'a'任然是null,最后得到的value永远是null。所以默认是''

b.第二个fetch语句一定要放在begin和end之间,要不然会死循环的,不常用的语句写起来很不爽快

经 scottshen提醒,使用for xml更加的简单,看下面的语句:

SELECT id,

(SELECT value + '' FROM #table2 WHERE id=a.id FOR XML PATH('')) AS [values]

FROM #table2 AS a GROUP BY a.id

--或者这样写

select distinct a.id,

(select b.value+'' from #table2 b where b.id=a.id for XML path('')) as value

from #table2 a

下面这一句帮助我们理解for xml的工作原理

select ''+a.value from #table2 a where id=2 for xml path('')

oracle创建交叉表,SQL交叉表常用实例(转载网络)相关推荐

  1. Oracle 创建用户授权,建表

    1.SQL*Plus命令行工具使用:在命令行中输入 sqlplus/nolog 即可启用该工具     连接到Oracle服务器:conn 用户名/密码 as 连接身份@服务器连接字符串     连接 ...

  2. oracle 创建用户、授权、表空间

    create用户 create user visiontv identified by visiontv default tablespace visiontv quota 10m on users; ...

  3. oracle创建序列,并建表使用

    创建序列:sql语句 创建表 对序列user_s进行初始化 插入数据

  4. mysql分表全局查询_mysql如何查询多样同样的表/sql分表查询、java项目日志表分表的开发思路/按月分表...

    之前开发的一个监控系统,数据库的日志表是单表,虽然现在数据还不大并且做了查询sql优化,不过以后数据库的日志表数据肯定会越来越庞大,将会导致查询缓慢,所以把日志表改成分表,日志表可以按时间做水平分表, ...

  5. oracle创建存储过程动态sql,Oracle存储过程使用动态SQL

    Oracle存储过程使用动态SQL 有两种写法:用 DBMS_SQL 或 execute immediate,建议使用后者.试验步骤如下: 1:DDL和DML /*** DDL ***/ begin ...

  6. 在Oracle中执行动态SQL的几种方法------转载

    在Oracle中执行动态SQL的几种方法 在一般的sql操作中,sql语句基本上都是固定的,如: SELECT t.empno,t.ename  FROM scott.emp t WHERE t.de ...

  7. Oracle创建带有自增序列的表和字符串转日期的问题

    创建Oracle表的sql语句如下: --创建tm_product create table tm_product(pid number(8) primary key not null,product ...

  8. oracle创建登录用户有限制吗,Oracle创建用户限制文件,表空间用户授权等。

    1.用户限制文件(限制用户的使用)1 2 3 4create profile iyeeku_profile limit failed_login_attempts 5 -- 指定锁定用户的登录失败的次 ...

  9. oracle创建带blob字段的表,ORACLE 还有BLOB及CLOB等类型字段的表的导出导入

    当ORACLE数据库导出的时候,发现有些表有BLOB和CLOB类型字段的时候,利用一般的导出方法是无法导出的会报错,其原因是sql无法生成这两种类型字段,这个时候,最好用的方法就是plsql自带的导出 ...

  10. oracle创建索引01652,建立数据表快照导致ora-01652异常

    建立数据表快照导致ora-01652错误 由于源表过大,数据查询速度较慢,在做后台的相关查询的时候较慢,于是决定创建数据快照,提高查询速度,快照创建语句如下: CREATE SNAPSHOT sn_y ...

最新文章

  1. Redis的常用命令——set的常用命令
  2. oracle erp 库存相关,oracle erp库存模块表(INV)
  3. 推荐一款软件(作业)
  4. kaggle入门项目:Titanic存亡预测(三)数据可视化与统计分析
  5. java中的Vector的用法
  6. Windows 10 超过Windows 7成为最受欢迎的操作系统
  7. git The requested URL returned error: 403
  8. 2010年5月18日 小细节大隐患
  9. Redis 和 memcached 区别(二)
  10. mysql中日期相减_1104绝密公式,如何直接用2个日期直接算剩余时间区间
  11. MySQL嵌套查询(子查询)
  12. 2022年安全员-A证考题模拟考试平台操作
  13. 计算机管理有U盘 为啥不显示,U盘插入电脑后不显示怎么办?
  14. c语言正方形内切圆面积,c语言计算并输出某正方形内切圆的面积
  15. C++:缺省参数是怎样设置的?
  16. ELK+grok+华为防火墙USG6500会话日志
  17. nc6400 在bios中打开SATA模式就会蓝屏呢
  18. 网络安全控制网管解决方案
  19. E1 CE1 T1 BRI PRI
  20. pythonmultiprocessing之 queue线程_python中的进程、线程(threading、multiprocessing、Queue、subprocess)...

热门文章

  1. 50以内的勾股数c语言,50以内勾股数有哪些
  2. 将yolo格式数据集转换为coco格式数据集
  3. 互联网计算机远程建立连接怎么回事,qq远程协助一直正在建立连接?最全分析解决方法送上!...
  4. 用计算机术语写毕业寄语,大学毕业寄语(精选50句)
  5. 减法公式运算法则_小学所有的运算定律和什么叫加法什么叫减法,乘法a+b=c什么的公式也要...
  6. 纯css画一个月亮的天气图标
  7. html自我介绍怎么弄,用html设计一个自我介绍的静态网页
  8. 硬核干货|揭示波士顿动力机器人背后的专利技术(上)
  9. 【linux内核分析与应用-陈莉君】内核同步概述
  10. android 盒子 红白机 模拟器,安卓FC模拟器