sql学习:SQL综合应用学习



看完测试完下面这些试题SQL水平定会有新提高


下面我们先看下题设:
2维表 T(F1,F2,F3,F4,F5,F6,F7) 表示如下关系:
┌─────┬────┬─────┬─────┬─────┬─────┬─────┐
│ 学生ID │学生姓名│ 课程ID │ 课程名称 │ 成绩 │ 教师ID │ 教师姓名 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S3 │ 王 5 │ K4 │ 政治 │ 53 │ T4 │ 赵老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S1 │ 张 3 │ K1 │ 数学 │ 61 │ T1 │ 张老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S2 │ 李 4 │ K3 │ 英语 │ 88 │ T3 │ 李老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S1 │ 张 3 │ K4 │ 政治 │ 77 │ T4 │ 赵老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S2 │ 李 4 │ K4 │ 政治 │ 67 │ T5 │ 周老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S3 │ 王 5 │ K2 │ 语文 │ 90 │ T2 │ 王老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S3 │ 王 5 │ K1 │ 数学 │ 55 │ T1 │ 张老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S1 │ 张 3 │ K2 │ 语文 │ 81 │ T2 │ 王老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S4 │ 赵 6 │ K2 │ 语文 │ 59 │ T1 │ 王老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S1 │ 张 3 │ K3 │ 英语 │ 37 │ T3 │ 李老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ S2 │ 李 4 │ K1 │ 数学 │ 81 │ T1 │ 张老师 │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ .... │ │ │ │ │ │ │
├─────┼────┼─────┼─────┼─────┼─────┼─────┤
│ .... │ │ │ │ │ │ │
└─────┴────┴─────┴─────┴─────┴─────┴─────┘
为便于大家更好理解,我们将 T 表起名为\"成绩表\"

1.如果 T 表还有字段 F 数据类型为自动增量整型(唯,不会重复),


而且 T 表中含有除 F 字段外,请删除其它字段完全相同重复多余脏记录数据:

本问题就是个清理\"逻辑重复\"记录问题,当然,这种情况完全可以利用主键约束来
杜绝!然而,现实情况经常是原始数据在\"洗涤\"后,方可安全使用,而且逻辑主键过早
约束,将会给采集原始数据带来不便,例如:从刷卡机上读取考勤记录到了应用数据
时候,脏数据就该被扫地出门了! 的所以题中要保留个自动标识列,是
是下面答案所必须前提:

DELETE L
FROM \"成绩表\" L
JOIN \"成绩表\" R
_disibledevent=> 这是思路最精巧且最直接有效思路方法的用不等自联接,正好可以将同组重复数
据中 F 字段值最小条留下,并选出其它删掉,如果只有条,自然也不会被选
中了这里还要强调下,大家定要分清楚被操作基本表也就是 DELETE 关键字
表和过滤条件所使用由基本表连接而成 2维表数据集,也就是 FROM 子句
全部在自连接 FROM 子句至少要取个别名来引用基本表别名使用在编写大
量类似结构 SQL 时非常方便,而且利于统构造动态 SQL如有必要加强条件,
还可继续使用 WHERE 子句如果上面例子还不够直观,下面模仿个不等自联接,
组数 (1,2,3),作个不等自联接,令左子集大于右子集,是:
2 1
3 1
3 2
如果现在选出左子集,就是 2 和 3 了1 在右边没有比它更小数据可以和的匹配,
因此被过滤了如果数据大量重复,效率会差强人意,幸亏不是 SELECT ,而是 DELETE
无需返回结果集,影响自然小多了

DELETE T
FROM 成绩表 T
WHERE F NOT IN (SELECT MIN(F)
FROM 成绩表 I
GROUP BY I.学生ID,I.课程ID
HAVING COUNT(*)>1
)
AND F NOT IN (SELECT MIN(F)
FROM 成绩表 I
GROUP BY I.学生ID, I.课程ID
HAVING COUNT(*)=1
)

这种思路方法思路很简单,就像翻译自然语言,很精确地描述了符合条件记录特性,甚至
第 2个条件确多余至少应该用个 >= 号合并这两个条件或只保留任意个条件,
提高效率

DELETE T
FROM 成绩表 T
WHERE F > (SELECT MIN(F)
FROM 成绩表 AS I
WHERE I.学生ID = T.学生ID
AND I.课程ID = T.课程ID
GROUP BY I.学生ID, I.课程ID
)

这种思路方法,基本上是思路方法相关子查询版本,了解笛卡尔积读者能会好理解些,而
且用到了统计,因此效率不是太高细心读者会发现子查询里 GROUP BY 子
句没有必要,去掉它应该会提高些效率

有关 DELETE 语句调试,有经验员都会先用无害 SELECT 暂时代替危险
DELETE例如:

SELECT L.*
--DELECT L 暂时注释掉
FROM \"成绩表\" L
JOIN \"成绩表\" R
_disibledevent=> 这样,极大地减小了在线数据被无意破坏可能性,当然数据提前备份也很重要同理
UPDATE 和 INSERT 写操作也应照此行事从数据库原理关系运算角度来看 INSERT、
UPDATE 和 DELETE 这些写操作都属于典型\"选择(Selection)\"运算,UPDATE 和 INSERT
而且还是\"投影(Projection)\"运算,它们都是这些关系运算\"写\"应用表现形式
其实,查询也本来无非就是浏览、删除、更
新或插入通常写操作也比读操作消耗更大,如果索引过多,只会降低效率

选择\"子查询\"还是\"连接\"在效率是有差别,但最关键差别还是表现在查询结果
读写性上,开发人员在写个\"只读\"应用查询记录集时,\"子查询\"和\"连接\"各自
效率就是应该首先考虑问题,但是如果要实现\"可写\"应用查询结果集,则无论是


相关还是非相关子查询都是在复杂应用中难以避免

以上解决方案中,应该说第种思路方法,简洁有效,很有创意,是值得推荐思路方法当然,
最简单写法应该是:

DELETE T
FROM T,T T1
WHERE T.学生ID=T1.学生ID and T.课程ID=T.课程ID and T.F < T1.F

其实这就是思路方法\"标准\"(但确实实不是ANSI/ISO SQL标准)连接写法,以下各
题答案为了便于读者理解,般不采用这种写法,这也是ANSI/ISO SQL标准所鼓
,JOIN 确实更容易地表达表的间关系,有兴趣读者可自行改写如果使用
\"*=\"实现两表以上外连接时,要注意此时 WHERE 子句 AND 条件是有顺序,尽
ANSI/ISO SQL标准不允许 WHERE 条件顺序影响查询结果,但是 FROM 子句
各表连接顺序可以影响查询结果

2.列印各科成绩最高和最低相关记录: (就是各门课程最高、最低分学生和老师)
课程ID,课程名称, 最高分,学生ID,学生姓名,教师ID,教师姓名, 最低分,学生ID,学生姓名,教师ID,教师姓名

如果这道题要是仅仅求出各科成绩最高分或最低分,则是道非常简单题了:

SELECT L.课程ID, MAX(L.课程名称), MAX(L.成绩) AS 最高分, MIN(L.成绩) AS 最低分
FROM 成绩表 L
GROUP BY L.课程ID

但是,刁钻题目却是要列出各科最高和最低成绩相关记录,这也往往才是真正需求
既然已经选出各科最高和最低分,那么,剩下就是把学生和教师信息并入这个结果
如果照这样写下去,非常麻烦,要添加字段太多了,很快就使代码变得难于
管理还是换个思路吧:

SELECT L.课程ID,L.课程名称,L.[成绩] AS 最高分,L.[学生ID],L.[学生姓名],L.[教师ID],L.[教师姓名]
,R.[成绩] AS 最低分,R.[学生ID],R.[学生姓名],R.[教师ID],R.[教师姓名]
FROM 成绩表 L
JOIN 成绩表 AS R _disibledevent=> WHERE L.[成绩] = (SELECT MAX(IL.[成绩])
FROM 成绩表 AS [IL]
WHERE L.[课程ID] = IL.[课程ID]
GROUP BY IL.[课程ID]
)
AND
R.[成绩] = (SELECT MIN(IR.[成绩])
FROM 成绩表 AS [IR]
WHERE R.[课程ID] = IR.[课程ID]
GROUP BY IR.[课程ID]
)

看答案,好像很复杂,其实如果掌握了构造交叉透视表基本思路方法和相关子查询
知识,问题迎刃而解由于最低和最高分都是针对课程信息,该答案巧妙地把课程信
息合并到了最高分数据集中,当然也可以合并到最低分中代码中规中矩,风格很好,
可读性也是不错

3.按平均成绩从高到低顺序,列印所有学生 4门(数学,语文,英语,政治)课程成绩: (就是每个学生 4门课程成绩单)
学生ID,学生姓名,数学,语文,英语,政治,有效课程数,有效平均分
(注: 有效课程即在 T 表中有该学生成绩记录,如不明白可不列印\"有效课程数\"和\"有效平均分\")

需要介绍说明是: 题目的所以明确提出\" 4门(数学,语文,英语,政治)课程\"是有道理,
实现时,确无法避免使原基本表中行上数据值影响列,这又是个典型
\"行变列\"相关子查询:

SELECT 学生ID,MAX(学生姓名) AS 学生姓名,
(SELECT 成绩 FROM 成绩表 WHERE 学生ID=T.学生ID AND 课程ID=\'K1\') AS 数学 ,
(SELECT 成绩 FROM 成绩表 WHERE 学生ID=T.学生ID AND 课程ID=\'K2\') AS 语文 ,
(SELECT 成绩 FROM 成绩表 WHERE 学生ID=T.学生ID AND 课程ID=\'K3\') AS 英语 ,
(SELECT 成绩 FROM 成绩表 WHERE 学生ID=T.学生ID AND 课程ID=\'K4\') AS 政治 ,
COUNT(*) AS 有效课程数, AVG(T.成绩) AS 平均成绩
FROM 成绩表 AS T
GROUP BY 学生ID
ORDER BY 平均成绩

这可以说也是个很规矩解法,在这种应用场合,子查询要比联接代码可读性强得多
如果数据库引擎认为把它解析成联接更好,那就由它去吧,其实本来相关子查询也肯定含有连接
这里再补充下,在实际应用中如果再加张表 Ranks(Rank,MinValue,MaxValue):

┌─────┬─────┬─────┐
│ Rank │ MinValue │ MaxValue │


├─────┼─────┼─────┤
│ A │ 90 │ 100 │
├─────┼─────┼─────┤
│ B │ 80 │ 89 │
├─────┼─────┼─────┤
│ C │ 70 │ 79 │
├─────┼─────┼─────┤
│ D │ 60 │ 69 │
├─────┼─────┼─────┤
│ E │ 0 │ 59 │
└─────┴─────┴─────┘

就可以实现个非常有实用价值应用:

select 学生ID,MAX(学生姓名) as 学生姓名
,(select 成绩 from 成绩表 t where 学生ID=T0.学生ID and 课程ID=\'K1\') as 数学
,(SELECT max(Rank) from Ranks ,成绩表 t
where t.成绩 >= Ranks.MinValue
and t.成绩 <= Ranks.MaxValue
and t.学生ID=T0.学生ID and t.课程ID=\'K1\'
) as 数学级别
,(select 成绩 from 成绩表 t where 学生ID=T0.学生ID and 课程ID=\'K2\') as 语文
,(SELECT min(Rank)
from Ranks ,成绩表 t
where t.成绩 >= Ranks.MinValue
and t.成绩 <= Ranks.MaxValue
and t.学生ID=T0.学生ID and t.课程ID=\'K2\'
) as 语文级别
,(select 成绩 from 成绩表 t where 学生ID=T0.学生ID and 课程ID=\'K3\') as 英语
,(SELECT max(Rank)
from Ranks ,成绩表 t
where t.成绩 >= Ranks.MinValue
and t.成绩 <= Ranks.MaxValue
and t.学生ID=T0.学生ID and t.课程ID=\'K3\'
) as 英语级别
,(select 成绩 from 成绩表 t where 学生ID=T0.学生ID and 课程ID=\'K4\') as 政治
,(SELECT min(Rank)
from Ranks ,成绩表 t
where t.成绩 >= Ranks.MinValue
and t.成绩 <= Ranks.MaxValue
and t.学生ID=T0.学生ID and t.课程ID=\'K4\'
) as 政治级别
,count(*),avg(t0.成绩)
,(SELECT max(Rank)
from Ranks
where AVG(T0.成绩) >= Ranks.MinValue
and AVG(T0.成绩) <= Ranks.MaxValue
) AS 平均级别
from 成绩表 t0
group by 学生ID

这里表面上使用了不等连接,再仔细想想,Ranks 表中每条记录区间是没有交集,
其实也可以认为是等值连接,这样表设计无疑存在着良好扩展性,如果题目只要求

列印(学生ID,学生姓名,有效课程数,有效平均分,平均分级别):

select 学生ID,MAX(学生姓名) as 学生姓名,count(*),avg(t0.成绩)
,(SELECT max(Rank)
from Ranks
where AVG(T0.成绩) >= Ranks.MinValue
and AVG(T0.成绩) <= Ranks.MaxValue


) AS 平均级别
from T as T0
group by 学生ID

则这样解决方案就比较全面了

回到原题,再介绍个比较取巧办法,仅需个简单分组查询就可解决问题,有经验读者可能已经想到了
,那就是 CASE:

SELECT 学生ID, MIN(学生姓名),
SUM(CASE 课程ID WHEN \'K1\' THEN 成绩 ELSE 0 END) AS 数学,
SUM(CASE 课程ID WHEN \'K2\' THEN 成绩 ELSE 0 END) AS 语文,
SUM(CASE 课程ID WHEN \'K3\' THEN 成绩 ELSE 0 END) AS 英语,
SUM(CASE 课程ID WHEN \'K4\' THEN 成绩 ELSE 0 END) AS 政治,
COUNT(*) AS 有效课程数, AVG(T.成绩) AS 平均成绩
FROM 成绩表 AS T
GROUP BY 学生ID
ORDER BY 平均成绩 DESC

虽然可能初看答案感觉有点怪,其实很好理解,可读性并不低,效率也很高但它不能
像前个答案那样,在成绩中区分出某门课这个学生究竟是缺考 (NULL),还是真得
零分这个解法充分利用了 CASE 语句进行数据分类作用: CASE 将成绩按课程分
成 4类,SUM 用来消去多余 0

SELECT [T].[学生ID],MAX([T].[学生姓名]) AS 学生姓名,
MAX([T1].[成绩]) AS 数学,
MAX([T2].[成绩]) AS 语文,
MAX([T3].[成绩]) AS 英语,
MAX([T4].[成绩]) AS 政治,
COUNT([T].[课程ID]) AS 有效课程数,
(ISNULL(MAX([T1].[成绩]),0) +
ISNULL(MAX([T2].[成绩]),0) +
ISNULL(MAX([T3].[成绩]),0) +
ISNULL(MAX([T4].[成绩]),0)) / COUNT([T].[课程ID]) AS 有效平均分
FROM 成绩表 T
LEFT JOIN 成绩表 AS [T1] _disibledevent=> LEFT JOIN 成绩表 AS [T2] _disibledevent=> LEFT JOIN 成绩表 AS [T3] _disibledevent=> LEFT JOIN 成绩表 AS [T4] _disibledevent=>GROUP BY [T].[学生ID]
ORDER BY 有效平均分 DESC

这个思路方法是相当正统联接解法,尽管写起来麻烦了些,但还是不难理解再从实用
角度考虑下,真实需求往往不是象本题明确提出\"列印 4门 (数学,语文,英语,政治)
课程\"这样相对静态需求,该是动态 SQL 大显身手时候了,很明显思路方法写法
无疑是利用构造动态 SQL 最好选择,当然另两个 SQL 规律还是挺明显,同样
不难构造以 CASE 版答案为例: 先用个游标遍历,取出所有课程凑成:
SUM(CASE \'课程ID\' WHEN \'课程名称\' THEN 成绩 ELSE 0 END) AS 课程名称 形式,
再补上 SELECT 和 FROM、WHERE 等必要条件,个生成动态成绩单 SQL 就诞生了,
只要再由相关执行即可,这样就可以算个更完善解决方案了

其实,最类似典型应用是在主、细关系中主表投影中实现细表汇总统计行,
例如两张表:
Master(F,f1,f2 ...) 对多 Details(F,f3,f4 ...)
SELECT *
,( SELECT COUNT(*)
FROM Details
WHERE Master.F = Details.F
)
,( SELECT SUM(F3)
FROM Details
WHERE Master.F = Details.F
)
FROM Master

4.按各科不平均成绩从低到高和及格率百分数从高到低顺序,统计并列印各科平均成绩和不及格率百分数(用\"N行\"表示):
(就是分析哪门课程难)
课程ID,课程名称,平均成绩,及格百分比
SELECT 课程ID,MAX(课程名称) AS 课程名称,AVG(成绩) AS 平均成绩
,str(100 * SUM(CASE WHEN 成绩 >=60 THEN 1 ELSE 0 END)/COUNT(*))+\'%\' AS 及格百分比
FROM 成绩表 T
GROUP BY 课程ID
ORDER BY 及格百分比 DESC

这道题应该说是算简单了,就是用\"行\"来提供表现形式只要想明白要对数据如
何分组,取统计聚集,就万事大吉了

5.列印 4门课程平均成绩和及格率百分数(用\"1行4列\"表示): (就是分析哪门课程难)
数学平均分,数学及格百分数,语文平均分,语文及格百分数,英语平均分,英语及格百分数,政治平均分,政治及格百分数

这道题其实就是上\"列\"表现形式版本,相对于上题,本题是静态,本题
同第 3题样利用行上数据构造了列,要实现扩展必须再利用另外构造动态
SQL:

SELECT SUM(CASE WHEN 课程ID = \'K1\' THEN 成绩 ELSE 0 END)/SUM(CASE 课程ID WHEN \'K1\' THEN 1 ELSE 0 END) AS 数学平均分


,100 * SUM(CASE WHEN 课程ID = \'K1\' AND 成绩 >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN 课程ID = \'K1\' THEN 1 ELSE 0 END) AS 数学及格百分数
,SUM(CASE WHEN 课程ID = \'K2\' THEN 成绩 ELSE 0 END)/SUM(CASE 课程ID WHEN \'K2\' THEN 1 ELSE 0 END) AS 语文平均分
,100 * SUM(CASE WHEN 课程ID = \'K2\' AND 成绩 >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN 课程ID = \'K2\' THEN 1 ELSE 0 END) AS 语文及格百分数
,SUM(CASE WHEN 课程ID = \'K3\' THEN 成绩 ELSE 0 END)/SUM(CASE 课程ID WHEN \'K3\' THEN 1 ELSE 0 END) AS 英语平均分
,100 * SUM(CASE WHEN 课程ID = \'K3\' AND 成绩 >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN 课程ID = \'K3\' THEN 1 ELSE 0 END) AS 英语及格百分数
,SUM(CASE WHEN 课程ID = \'K4\' THEN 成绩 ELSE 0 END)/SUM(CASE 课程ID WHEN \'K4\' THEN 1 ELSE 0 END) AS 政治平均分
,100 * SUM(CASE WHEN 课程ID = \'K4\' AND 成绩 >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN 课程ID = \'K4\' THEN 1 ELSE 0 END) AS 政治及格百分数
FROM 成绩表 T

句看起来很长,但实际上是最经典 CASE 运用,很实用数据分析技术先将原
表中成绩列连续投影 8 次备用于 4门区别课程,充分利用 CASE 和数据值域
[\'k1\',\'k2\',\'k3\',\'k4\']来划分数据,再利用 SUM [1 + ...+ 1] 实现了看似本来应
该用 COUNT(*) 计数器功能,这里面不要说联接和子查询,甚至连 Group by 分组
痕迹都找不到!如果读起来吃力,完全可以先只保留个字段,相对好理解些,看懂后
补全本题也可以算个\"行变列\"交叉透视表举例吧! 另外,\"行\"相对于\"列\"
是动态,\"行\"是相对无限,\"列\"是相对有限,\"行\"增删是应用级,可\"随意\"增
删,\"列\"增删是管理级,不要轻易变动!

6.按区别老师所教区别课程平均分从高到低列印: (就是分析哪个老师哪个课程水平高)
教师ID,教师姓名,课程ID,课程名称,平均分

SELECT 教师ID,MAX(教师姓名) AS 教师姓名,课程ID,MAX(课程名称) AS 课程名称,AVG(成绩) AS 平均成绩
FROM 成绩表 T
GROUP BY 课程ID,教师ID
ORDER BY AVG(成绩) DESC

这道题确没啥好说,就算闭着眼,不动手,答案也应脱口而出!
如果平均分按去掉个最高分和个最低分后取得,则也不难写出:

SELECT 教师ID,MAX(教师姓名),课程ID,MAX(课程名称) AS 课程名称 --,AVG(成绩) AS 平均成绩
,(SUM(成绩)
-(SELECT MAX(成绩)
FROM 成绩表
WHERE 课程ID= T1.课程ID AND 教师ID = T1.教师ID)
-(SELECT MIN(成绩)
FROM 成绩表
WHERE 课程ID= T1.课程ID and 教师ID = T1.教师ID))
/ CAST((SELECT COUNT(*) -2
FROM 成绩表
WHERE 课程ID= T1.课程ID AND 教师ID = T1.教师ID) AS FLOAT) AS 平均分
FROM 成绩表 AS T1
WHERE (SELECT COUNT(*) -2
FROM 成绩表
WHERE 课程ID = T1.课程ID AND 教师ID = T1.教师ID) >0
GROUP BY 课程ID,教师ID
ORDER BY 平均分 DESC
********************************************************************************************
7.列印数学成绩第 10 名到第 15 名学生成绩单
或列印平均成绩第 10 名到第 15 名学生成绩单
[学生ID],[学生姓名],数学,语文,英语,政治,平均成绩

如果只考虑门课程,如:数学成绩,非常简单:
select Top 5 *
from T
where 课程id =\'K1\'
and 成绩 not in(select top 15 成绩
from T
order by 成绩 desc
)
order by 成绩 desc
union
select *
from T
where 课程id =\'K1\'
and 成绩 not in(select top 10 成绩
from T


order by 成绩 desc
)
and 成绩 in(select top 15 成绩
from T
order by 成绩 desc
)
order by 成绩 desc

从逻辑上说,第 10 名到第 15 名就是从原前 15 名,\"再\"挑出前 5 名不要,保留剩下
5 名第 2种写法是从前 15 名里挑出不属于原前 10 名记录,把两个数据集做
个差,因此要多用
子查询,效率相对较低,它,如果要有ANSI/ISO SQL EXCEPT
关键字就是最理想

这种窍门技巧在数据\"分页\"应用中经常利用,只要遵循如下原则即可:

SELECT Top @PageSize *
FROM T
WHERE SortField NOT IN (SELECT TOP @PageSize * @Pagei SortField
FROM T
ORDER BY SortField
)
ORDER BY SortField

至此,该题考察主要目已经达到至于列印明晰成绩单:
[学生ID],[学生姓名],数学,语文,英语,政治,平均成绩 前面也有类似题目,做起来
确实麻烦,因此下面仅提供参考答案,就不赘述了:

SELECT DISTINCT top 5
[成绩表].[学生ID],
[成绩表].[学生姓名] AS 学生姓名,
[T1].[成绩] AS 数学,
[T2].[成绩] AS 语文,
[T3].[成绩] AS 英语,
[T4].[成绩] AS 政治,
ISNULL([T1].[成绩],0) + ISNULL([T2].[成绩],0) + ISNULL([T3].[成绩],0) + ISNULL([T4].[成绩],0) as 总分
FROM [成绩表]
LEFT JOIN [成绩表] AS [T1]
_disibledevent=> LEFT JOIN [成绩表] AS [T2]
_disibledevent=> LEFT JOIN [成绩表] AS [T3]
_disibledevent=> LEFT JOIN [成绩表] AS [T4]
_disibledevent=>WHERE ISNULL([T1].[成绩],0) + ISNULL([T2].[成绩],0) + ISNULL([T3].[成绩],0) + ISNULL([T4].[成绩],0)
NOT IN
(SELECT
DISTINCT
TOP 15 WITH TIES
ISNULL([T1].[成绩],0) + ISNULL([T2].[成绩],0) + ISNULL([T3].[成绩],0) + ISNULL([T4].[成绩],0)
FROM [成绩表]
LEFT JOIN [成绩表] AS [T1]
_disibledevent=> LEFT JOIN [成绩表] AS [T2]
_disibledevent=> LEFT JOIN [成绩表] AS [T3]


_disibledevent=> LEFT JOIN [成绩表] AS [T4]
_disibledevent=> ORDER BY ISNULL([T1].[成绩],0) + ISNULL([T2].[成绩],0) + ISNULL([T3].[成绩],0) + ISNULL([T4].[成绩],0) DESC)

最后还要多说句: 般 TOP 关键字和 ORDER BY 子句合用才有真正意义

Tags:  sql应用 sql语言学习 sqlserver学习 sql学习

延伸阅读

最新评论

发表评论