需求数据如下:
CREATE TABLE foo( num VARCHAR2(10)); INSERT INTO foo VALUES('0001'); INSERT INTO foo VALUES('0002'); INSERT INTO foo VALUES('0003'); INSERT INTO foo VALUES('0007'); INSERT INTO foo VALUES('0008'); INSERT INTO foo VALUES('0019'); INSERT INTO foo VALUES('0020'); INSERT INTO foo VALUES('0022');
SELECT LPAD(TO_NUMBER(A.NUM)+1, LENGTH(A.NUM), 0) AS NUM, RANK() OVER(ORDER BY A.NUM) AS NG FROM FOO A WHERE NOT EXISTS (SELECT 1 FROM FOO B WHERE TO_NUMBER(A.NUM) + 1 = TO_NUMBER(B.NUM))
2)如果下一个数字不存在于本列中,则符合条件,得到的结果如下:0000、0006、0018、0021
SELECT LPAD(TO_NUMBER(A.NUM)-1, LENGTH(A.NUM), 0) AS NUM, RANK() OVER(ORDER BY A.NUM) AS NG FROM FOO A WHERE NOT EXISTS (SELECT 1 FROM FOO B WHERE TO_NUMBER(A.NUM) - 1 = TO_NUMBER(B.NUM))
3)上面使用RANK()分析函数得到了ROWNUM,通过ROWNUM关联得到结果,形成最终的SQL
SELECT O.NUM,P.NUM FROM ( SELECT LPAD(TO_NUMBER(A.NUM)+1, LENGTH(A.NUM), 0) AS NUM, RANK() OVER(ORDER BY A.NUM) AS NG FROM FOO A WHERE NOT EXISTS (SELECT 1 FROM FOO B WHERE TO_NUMBER(A.NUM) + 1 = TO_NUMBER(B.NUM)) ) O, ( SELECT LPAD(TO_NUMBER(A.NUM)-1, LENGTH(A.NUM), 0) AS NUM, RANK() OVER(ORDER BY A.NUM) AS NG FROM FOO A WHERE NOT EXISTS (SELECT 1 FROM FOO B WHERE TO_NUMBER(A.NUM) - 1 = TO_NUMBER(B.NUM)) )P WHERE O.NG+1 = P.NG
今天财务总监说老板想看这样的统计信息,每周的销售情况。
所以要写如题函数 :
-- ============================================= -- Author: <David Gong> -- Create date: <2013-01-11> -- Description: <查询指定日期所在年份第几周> -- ============================================= ALTER Function [dbo].[WeekOfDate] ( @Date DateTime --要转换的日期 )returns INT as begin DECLARE @Year int --取得年份 DECLARE @StFinanceDate VARCHAR(10) --年度第一天 DECLARE @StarDay DateTime --年度第一天,日期类 DECLARE @DayDiff int DECLARE @Ret int --返回结果 SET @Year =DATEPART(year, @Date) --取得所在年份 SET @StarDay= CAST(@Year AS varchar)+'-01-01' SET @DayDiff= DATEDIFF(day, convert(datetime,@StarDay,120), @Date)+1 IF @DayDiff % 7=0 SET @Ret=@DayDiff/7 IF @DayDiff % 7<>0 SET @Ret=@DayDiff/7+1 Return @Ret end报表:
函数参考网友的会计期间转换日期:
http://www.cnblogs.com/wsdj-ITtech/archive/2010/07/03/1770617.html
在《数据库原理》里面,对聚簇索引的解释是:聚簇索引的顺序就是数据的物理存储顺序,而对非聚簇索引的解释是:索引顺序与数据物理排列顺序无关。正式因为如此,所以一个表最多只能有一个聚簇索引。
不过这个定义太抽象了。在SQL Server中,索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。如下图:
非聚簇索引
聚簇索引
聚簇索引与非聚簇索引的本质区别到底是什么?什么时候用聚簇索引,什么时候用非聚簇索引?
这是一个很复杂的问题,很难用三言两语说清楚。我在这里从SQL Server索引优化查询的角度简单谈谈(如果对这方面感兴趣的话,可以读一读微软出版的《Microsoft SQL Server 2000数据库编程》第3单元的数据结构引论以及第6、13、14单元)。
一、索引块与数据块的区别
大家都知道,索引可以提高检索效率,因为它的二叉树结构以及占用空间小,所以访问速度块。让我们来算一道数学题:如果表中的一条记录在磁盘上占用1000字节的话,我们对其中10字节的一个字段建立索引,那么该记录对应的索引块的大小只有10字节。我们知道,SQL Server的最小空间分配单元是“页(Page)”,一个页在磁盘上占用8K空间,那么这一个页可以存储上述记录8条,但可以存储索引800条。现在我们要从一个有8000条记录的表中检索符合某个条件的记录,如果没有索引的话,我们可能需要遍历8000条×1000字节/8K字节=1000个页面才能够找到结果。如果在检索字段上有上述索引的话,那么我们可以在8000条×10字节/8K字节=10个页面中就检索到满足条件的索引块,然后根据索引块上的指针逐一找到结果数据块,这样IO访问量要少的多。
二、索引优化技术
是不是有索引就一定检索的快呢?答案是否。有些时候用索引还不如不用索引快。比如说我们要检索上述表中的所有记录,如果不用索引,需要访问8000条×1000字节/8K字节=1000个页面,如果使用索引的话,首先检索索引,访问8000条×10字节/8K字节=10个页面得到索引检索结果,再根据索引检索结果去对应数据页面,由于是检索所有数据,所以需要再访问8000条×1000字节/8K字节=1000个页面将全部数据读取出来,一共访问了1010个页面,这显然不如不用索引快。
SQL Server内部有一套完整的数据检索优化技术,在上述情况下,SQL Server的查询计划(Search Plan)会自动使用表扫描的方式检索数据而不会使用任何索引。那么SQL Server是怎么知道什么时候用索引,什么时候不用索引的呢?SQL Server除了日常维护数据信息外,还维护着数据统计信息,下图是数据库属性页面的一个截图:
从图中我们可以看到,SQL Server自动维护统计信息,这些统计信息包括数据密度信息以及数据分布信息,这些信息帮助SQL Server决定如何制定查询计划以及查询是是否使用索引以及使用什么样的索引(这里就不再解释它们到底如何帮助SQL Server建立查询计划的了)。我们还是来做个实验。建立一张表:tabTest(ID, unqValue,intValue),其中ID是整形自动编号主索引,unqValue是uniqueidentifier类型,在上面建立普通索引,intValue 是整形,不建立索引。之所以挂上一个没有索引的intValue字段,就是防止SQL Server使用索引覆盖查询优化技术,这样实验就起不到作用了。向表中录入10000条随机记录,代码如下:
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[unqValue] [uniqueidentifier] NOT NULL ,
[intValue] [int] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tabTest] WITH NOCHECK ADD
CONSTRAINT [PK_tabTest] PRIMARY KEY CLUSTERED
(
[ID]
) ON [PRIMARY]