正确高效的编写sql语句的境界是将一个复杂问题分解成一个一个简单的小问题。

雨燕fly 2012-07-26 07:12:45
很多人觉得sql简单,select,where的简单例子让人们产生了一种误解:sql不过如此,没有什么精妙可言。可是,我要对那些在心中没有sql地位的人说一句:sql是一门计算机语言,它的编写过程蕴含了精妙的逻辑思维,它的功能十分强大,足可以跟java,c#媲美。我瞧不起那种没有学习几天sql就对它指指点点的人,也瞧不起那种拿到sql程序上上下下看几眼就告诉别人它是干什么的人。我觉得至少需要2个月的时间,每天有2个小时的学习与实践时间才能真正的入门sql,才会体会出sql的精妙的逻辑思维。
上面我说了sql的入门,下面我想说一下sql的提高和编写sql的境界。我认为正确编写sql的境界是:将一个复杂问题分解成一个一个简单的小问题。例如我要实现三个表的联查的时候,我分为以下几个步骤:
(1)首先从port_e1表中查出e1端口的条数:
select * from port_e1;
结果为为295条。
(2)然后联查一下port表和port_e1表:
select
`port`.`PORT_ID` AS `PORT_ID`,
`port`.`CARD_ID` AS `CARD_ID`,
`port`.`PORT_INDEX` AS `PORT_INDEX`,
`port`.`PORT_NAME` AS `PORT_NAME`,
`port_e1`.`LOOPBACK_TYPE` AS `LOOPBACK_TYPE`
from `port`
JOIN `port_e1` ON (`port`.`PORT_ID`= `port_e1`.`PORT_ID`);
得出的记录仍然应该是295条,说明我这一步是正确的。
(3)最后根据左联查,查出e1对应的Z1_TP:
select
`port`.`PORT_ID` AS `PORT_ID`,
`port`.`CARD_ID` AS `CARD_ID`,
`port`.`PORT_INDEX` AS `PORT_INDEX`,
`port`.`PORT_NAME` AS `PORT_NAME`,
`port_e1`.`LOOPBACK_TYPE` AS `LOOPBACK_TYPE`,
ems_cxc_common.Z1_TP AS `Z1_TP`
from `port`
JOIN `port_e1` ON (`port`.`PORT_ID`= `port_e1`.`PORT_ID`)
LEFT JOIN ems_cxc_common ON (port_e1.PORT_ID = ems_cxc_common.Z1_TP)
最后结果仍然是295条。从而最后证明了我所编写的数据库脚本是正确的。
如果编写sql语句之前,没有清晰的条理,最后的结果一定会让你的脑袋瞬间爆炸。千万不要在脑袋里面构建一个sql的主题架构,然后立马运行脚本。别以为sql简单,自己可以掌控全局。当你执行毫无条理的sql,你面对的调试是非常困难的,你会想象不到的困难。
本文有鸟啼音本人原创。未经同意不得转载。
鸟啼音:www.birdsing.net
...全文
753 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoxiangqing 2012-07-29
  • 打赏
  • 举报
回复
深有同感
稻庄 2012-07-28
  • 打赏
  • 举报
回复
代码量与性能,你选择哪个?
bcc222 2012-07-28
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]

引用 5 楼 的回复:
楼主支持一下,我用的sql server,有的时候感觉很怪异,我们可能自己感觉是对的,但是实际上代码报错

如下面的代码,如果不对中间括号中的select增加别名的话,则编译的时候报错



SQL code

select c.username,avg(c.diff) from
(
select b.username ,b.department ……
[/Quote]

明白了,主要是看到楼主写的东西比较好,就把自己最近遇到的小困惑写了一些

不过我感觉最好是能在写完了语句以后,再回头来看看,能不能用更快的方法进行操作,这样才能有提高,先解决问题,再更好的解决问题
NET_2011 2012-07-28
  • 打赏
  • 举报
回复
如果指令设置为 CDATA,则不对包含的数据进行实体编码,而是将其放入 CDATA 部分。CDATA 属性必须没有名称。
zhouixi 2012-07-28
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
楼主支持一下,我用的sql server,有的时候感觉很怪异,我们可能自己感觉是对的,但是实际上代码报错

如下面的代码,如果不对中间括号中的select增加别名的话,则编译的时候报错



SQL code

select c.username,avg(c.diff) from
(
select b.username ,b.department ,datediff(hou……
[/Quote]

这个地方肯定要加别名的,这个别名相当一个表名。你不加SQL,理解成没有表名了。
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
楼主支持一下,我用的sql server,有的时候感觉很怪异,我们可能自己感觉是对的,但是实际上代码报错

如下面的代码,如果不对中间括号中的select增加别名的话,则编译的时候报错



SQL code

select c.username,avg(c.diff) from
(
select b.username ,b.department ,datediff(hou……
[/Quote]

这个是你把基本语法弄错了,当查询语句作为另外一个查询的输入表时(这样解释能看明白吧),必须取别名,也就是select * from(select * from tb where ....) as t(这个t可以随意换,as可以省略)
NET_2011 2012-07-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

如果指令设置为 CDATA,则不对包含的数据进行实体编码,而是将其放入 CDATA 部分。CDATA 属性必须没有名称。
[/Quote]
发错贴了

楼主有什么不明的,掌握表连接,性能看执行计划
雨燕fly 2012-07-27
  • 打赏
  • 举报
回复
感谢诸位的捧场。
bcc222 2012-07-27
  • 打赏
  • 举报
回复
楼主支持一下,我用的sql server,有的时候感觉很怪异,我们可能自己感觉是对的,但是实际上代码报错

如下面的代码,如果不对中间括号中的select增加别名的话,则编译的时候报错



select c.username,avg(c.diff) from
(
select b.username ,b.department ,datediff(hour,a.timestr,a.latetime) as diff
from worktodo a
left join users b
on a.userid=b.truename
) c--这个地方不加别名就报错
group by c.username



shoppo0505 2012-07-26
  • 打赏
  • 举报
回复
个人观点比较偏向于楼主的观点,每个存储过程,函数尽量简洁化。
但是出于性能的考虑,在简洁化的程度上,能一起处理的就一起处理。
發糞塗牆 2012-07-26
  • 打赏
  • 举报
回复
曾经在论坛看到一个贴,具体是什么忘了,还被推荐过得,觉得里面说的挺好的一句话的大概意思是:有些问题合起来做会更好,也有一些问题分开来做会更好,做了3年开发和1年DBA,得出其中一个经验是:数据库几乎没有一成不变的铁律(当然也有,比如面向集合的操作一定比面向过程的操作高效(针对关系数据库,其他的我不加评论),清晰、必要的注释等等。)。真的要根据实际情况去具体分析和测试,比如是用表关联还是用关联子查询的问题,连《SQL.Server.2008编程入门经典(第3版)》这本书上也不能给出绝对的答案。也要视乎两表大小、结果这些来具体判断。加之在《sql语言艺术》一书上举了一个例子:Oracle的,一个存储过程,非常长,运行了20多分钟,但是经过作者的优化,20秒出来了。就是他把很多本来可以一次性做但被开发人员分步做的步骤合起来,再修改一些索引之类的。我在做DBA调优的时候,也发现很多操作其实可以何在一起,然后用case when来替代,从速度、I/O上都有明显的提升甚至几个数量级的加快,所以我同意楼主的部分观点,但是我坚持还是要具体情况具体分析

34,587

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧