case 子句的用途
语法:
case
when 条件 1 then 值 1
when 条件 2 then 值 2
。。。。。。
when 条件 n then 值 n
else 值 else
end
case 子句相当于一个具有多个选择的语句,在多个不同的条件中,选择其中之一,与 java
语言的 case 语句类似。
例:如果表 chinese 的字段 bh 为 null,则返回 0,如果字段 bh 为 1,则返回 99,字段 bh 为其它
值,原样返回。
select
case
when bh is null then 0
when bh=1 then 99
else bh
end bhs,
xh,code
from chinese
一、利用 CASE 语句更新列值
执行本语句将性别为男的伙食补助修改为 120,女修改为 100
UPDATE TB_EMP2
SET 伙食补助=CASE WHEN 性别='男' then 120
WHEN 性别='女' then 100
END
当列 cj 的值为 74 时,修改其值为 80,, 为 97 时,修改其值为 100,其它值不变
update tb
set cj=(case cj when 74 then 80
when 97 then 100
else cj end);
当列 kc 的值为’语文’时,修改列 cj=cj+6,, 为’物理’时,修改其值为 cj+4,其它值不变
update tb
set cj=(case when kc='语文' then cj+6
when kc='物理' then cj+4
else cj end);
//////////////////////////////////////////////////
利用 CASE 语句进行更新列值
执行本语句将性别为男的伙食补助修改为 120,女修改为 100
UPDATE TB_EMP2
SET 伙食补助=CASE WHEN 性别='男' then 120
WHEN 性别='女' then 100
END
当列 cj 的值为 74 时,修改其值为 80,, 为 97 时,修改其值为 100,其它值不变
update tb
set cj=(case cj when 74 then 80
when 97 then 100
else cj end);
当列 kc 的值为’语文’时,修改列 cj=cj+6,, 为’物理’时,修改其值为 cj+4,其它值不变
update tb
set cj=(case when kc='语文' then cj+6
when kc='物理' then cj+4
else cj end);
case 语句在 SQL 中的使用方法
Case 具有两种格式。简单 Case 函数和 Case 搜索函数。
1.简单 Case 函数
CASE sex
WHEN '1' THEN '男'
WHEN '2' THEN '女'
ELSE '其他' END
2.搜索 case 函数
CASE WHEN sex = '1' THEN '男'
WHEN sex = '2' THEN '女'
ELSE '其他' END
这两种方式,可以实现相同的功能。简单 Case 函数的写法相对比较简洁,但是和 Case 搜索
函数相比,功能方面会有些限制,比如写判断式。
还有一个需要注意的问题,Case 函数只返回第一个符合条件的值,剩下的 Case 部分将会被
自动忽略。
--比如说,下面这段 SQL,你永远无法得到“第二类”这个结果
CASE WHEN col_1 IN ( 'a', 'b') THEN '第一类'
WHEN col_1 IN ('a') THEN '第二类'
ELSE'其他' END
Case 使用集锦
一,已知数据按照另外一种方式进行分组,分析。
下面的 Case 语句用在 Group by 子句中
有如下数据:(为了看得更清楚,我并没有使用国家代码,而是直接用国家名作为 Primary Key)
国家(country) 人口(population)
中国 600
美国 100
加拿大 100
英国 200
法国 300
日本 250
德国 200
墨西哥 50
印度 250
根据国家人口数据,统计亚洲和北美洲的人口数量。应该得到下面这个结果。
洲 人口
亚洲 1100
北美洲 250
其他 700
想要解决这个问题,你会怎么做?生成一个带有洲 Code 的 View,是一个解决方法,但是这
样很难动态的改变统计的方式。
如果使用 Case 函数,SQL 代码如下:
SELECT SUM(population),
CASE country
WHEN '中国' THEN '亚洲'
WHEN '印度' THEN '亚洲'
WHEN '日本' THEN '亚洲'
WHEN '美国' THEN '北美洲'
WHEN '加拿大' THEN '北美洲'
WHEN '墨西哥' THEN '北美洲'
ELSE '其他' END
FROM Table_A
GROUP BY CASE country
WHEN '中国' THEN '亚洲'
WHEN '印度' THEN '亚洲'
WHEN '日本' THEN '亚洲'
WHEN '美国' THEN '北美洲'
WHEN '加拿大' THEN '北美洲'
WHEN '墨西哥' THEN '北美洲'
ELSE '其他' END;
同样的,我们也可以用这个方法来判断工资的等级,并统计每一等级的人数。SQL 代码如
下;
SELECT
CASE WHEN salary <= 500 THEN '1'
WHEN salary > 500 AND salary <= 600 THEN '2'
WHEN salary > 600 AND salary <= 800 THEN '3'
WHEN salary > 800 AND salary <= 1000 THEN '4'
ELSE NULL END salary_class,
COUNT(*)
FROM Table_A
GROUP BY
CASE WHEN salary <= 500 THEN '1'
WHEN salary > 500 AND salary <= 600 THEN '2'
WHEN salary > 600 AND salary <= 800 THEN '3'
WHEN salary > 800 AND salary <= 1000 THEN '4'
ELSE NULL END;
二,用一个 SQL 语句完成不同条件的分组。
下面的 Case 语句用在聚集函数(SUM)中,同时也起到了行转列的作用
有如下数据
国家(country) 性别(sex) 人口(population)
中国 1 340
中国 2 260
美国 1 45
美国 2 55
加拿大 1 51
加拿大 2 49
英国 1 40
英国 2 60
按照国家和性别进行分组,得出结果如下
国家 男 女
中国 340 260
美国 45 55
加拿大 51 49
英国 40 60
普通情况下,用 UNION 也可以实现用一条语句进行查询。但是那样增加消耗(两个 Select 部
分),而且 SQL 语句会比较长。
下面是一个是用 Case 函数来完成这个功能的例子
SELECT country,
SUM( CASE WHEN sex = '1' THEN
population ELSE 0 END), --男性人口
SUM( CASE WHEN sex = '2' THEN
population ELSE 0 END) --女性人口
FROM Table_A
GROUP BY country;
这样我们使用 Select,完成对二维表的输出形式,充分显示了 Case 函数的强大。
三,在 Check 中使用 Case 函数。
下面的 Case 语句用在表的约束规则中
在 Check 中使用 Case 函数在很多情况下都是非常不错的解决方法。可能有很多人根本
就不用 Check,那么我建议你在看过下面的例子之后也尝试一下在 SQL 中使用 Check。
下面我们来举个例子
公司 A,这个公司有个规定,女职员的工资必须高于 1000 块。如果用 Check 和 Case 来表现
的话,如下所示
CONSTRAINT check_salary CHECK
( CASE WHEN sex = '2'
THEN CASE WHEN salary > 1000
THEN 1 ELSE 0 END
ELSE 1 END = 1 )
如果单纯使用 Check,如下所示
CONSTRAINT check_salary CHECK
( sex = '2' AND salary > 1000 )
女职员的条件倒是符合了,男职员就无法输入了。这是一个非常经典的用法!
四,根据条件有选择的 UPDATE。
下面的 Case 语句用在 update 子句中,如果进行两次更新,则可能会产生错误!
例,有如下更新条件
工资 5000 以上的职员,工资减少 10%
工资在 2000 到 4600 之间的职员,工资增加 15%
很容易考虑的是选择执行两次 UPDATE 语句,如下所示
--条件 1
UPDATE Personnel
SET salary = salary *
WHERE salary >= 5000;
--条件 2
UPDATE Personnel
SET salary = salary *
WHERE salary >= 2000 AND salary < 4600;
但是事情没有想象得那么简单,假设有个人工资 5000 块。首先,按照条件 1,工资减少
10%,变成工资 4500。接下来运行第二个 SQL 时候,因为这个人的工资是 4500 在 2000 到
4600 的范围之内, 需增加 15%,最后这个人的工资结果是 5175,不但没有减少,反而增加
了。如果要是反过来执行,那么工资 4600 的人相反会变成减少工资。暂且不管这个规章是
多么荒诞,如果想要一个 SQL 语句实现这个功能的话,我们需要用到 Case 函数。代码如
下:
UPDATE Personnel
SET salary = CASE WHEN salary >= 5000
THEN salary *
WHEN salary >= 2000 AND salary < 4600
THEN salary *
ELSE salary END;
这里要注意一点,最后一行的 ELSE salary 是必需的,要是没有这行,不符合这两个条
件的人的工资将会被写成 NUll,那可就大事不妙了。在 Case 函数中 Else 部分的默认值是
NULL,这点是需要注意的地方。
五.变更主键列的值
本质上任然是 Case 语句在 update 中的应用
一般情况下,要想把两条数据的 Primary key,a 和 b 交换,需要经过临时存储,拷贝,
读回数据的三个过程,要是使用 Case 函数的话,一切都变得简单多了。
p_key col_1 col_2
a 1 张三
b 2 李四
c 3 王五
假设有如上数据,需要把主键 a 和 b 相互交换。用 Case 函数来实现的话,代码如下
UPDATE SomeTable
SET p_key =
CASE WHEN p_key = 'a' THEN 'b'
WHEN p_key = 'b' THEN 'a'
ELSE p_key END
WHERE p_key IN ('a', 'b');
同样的也可以交换两个 Unique key。需要注意的是,如果有需要交换主键的情况发生,多半
是当初对这个表的设计进行得不够到位,建议检查表的设计是否妥当。
六,两个表数据是否一致的检查。
Case 函数中,可以使用下列子句:
BETWEEN AND ,
LIKE,
IS NULL,
IN, NOT IN
EXISTS 和 NOT EXISTS
Case 函数不同于 DECODE 函数。在 Case 函数中,可以使用 BETWEEN,LIKE,IS
NULL,IN,EXISTS 等等。比如说使用 IN,EXISTS,可以进行子查询,从而 实现更多的功能。
下面具个例子来说明,有两个表,tbl_A,tbl_B,两个表中都有 keyCol 列。现在我们对
两个表进行比较,tbl_A 中的 keyCol 列的数据如果在 tbl_B 的 keyCol 列的数据中可以找到,
返回结果'Matched',如果没有找到,返回结果'Unmatched'。
要实现下面这个功能,可以使用下面两条语句
1.使用 IN 的时候
SELECT keyCol,
CASE WHEN keyCol IN ( SELECT keyCol FROM tbl_B ) –when 中使用 in 子句
THEN 'Matched'
ELSE 'Unmatched' END Label
FROM tbl_A;
2.使用 EXISTS 的时候
SELECT keyCol,
CASE WHEN EXISTS ( SELECT * FROM tbl_B
WHERE = )
THEN 'Matched'
ELSE 'Unmatched' END Label
FROM tbl_A;
使用 IN 和 EXISTS 的结果是相同的。也可以使用 NOT IN 和 NOT EXISTS,但是这个
时候要注意 NULL 的情况。
七,在 Case 函数中使用合计函数
假设有下面一个表
学号(std_id) 课程 ID(class_id) 课程名(class_name) 主修 flag(main_class_flg)
100 1 经济学 Y
100 2 历史学 N
200 2 历史学 N
200 3 考古学 Y
200 4 计算机 N
300 4 计算机 N
400 5 化学 N
500 6 数学 N
有的学生选择了同时修几门课程(100,200)也有的学生只选择了一门课程(300,400,500)。
选修多门课程的学生,要选择一门课程作为主修,主修 flag 里面写入 Y。只选择一门课程
的学生,主修 flag 为 N(实际上要是写入 Y 的话,就没有下面的麻烦事了,为了举例子,还
请多多包含)。
现在我们要按照下面两个条件对这个表进行如下查询 :
只选修一门课程的学生,返回那门课程的 ID
选修多门课程的学生,返回所选的主课程 ID
简单的想法就是,执行两条不同的 SQL 语句进行查询。
--条件 1:只选择了一门课程的学生
SELECT std_id, MAX(class_id) AS main_class
FROM Studentclass
GROUP BY std_id
HAVING COUNT(*) = 1;
执行结果 1
STD_ID MAIN_class
------ ----------
300 4
400 5
500 6
--条件 2:选择多门课程的学生
SELECT std_id, class_id AS main_class
FROM Studentclass
WHERE main_class_flg = 'Y' ;
执行结果 2
STD_ID MAIN_class
------ ----------
100 1
200 3
如果使用 Case 函数,我们只要一条 SQL 语句就可以解决问题,具体如下所示
SELECT std_id,
CASE WHEN COUNT(*) = 1 THEN MAX(class_id) --只选择一门课程的学生的情况
ELSE MAX(CASE WHEN main_class_flg = 'Y'
THEN class_id
ELSE NULL END
)
END AS main_class
FROM Studentclass
GROUP BY std_id;
运行结果
STD_ID MAIN_class
------ ----------
100 1
200 3
300 4
400 5
500 6
通过在 Case 函数中嵌套 Case 函数,在合计函数中使用 Case 函数等方法,我们可以轻松的
解决这个问题。使用 Case 函数给我们带来了更大的自由度。
最后提醒一下使用 Case 函数的新手注意不要犯下面的错误
CASE col_1
WHEN 1 THEN 'Right'
WHEN NULL THEN 'Wrong'
END
在这个语句中 When Null 这一行总是返回 unknown,所以永远不会出现 Wrong 的情况。因
为这句可以替换成 WHEN col_1 = NULL,这是一个错误的用法,这个时候我们应该选择用
WHEN col_1 IS NULL。正确的做法是:
CASE col_1
WHEN 1 THEN 'Right'
WHEN IS NULL THEN 'Wrong'
END
coalesce 函数
语法:coalesce(param1,param2)
当第一个参数 param1(通常为字段)为 null 时,返回第二个参数 param2 的值,否则,返
回第一个参数的值.这个函数与 NVL 函数功能相同。
例:
select coalesce(bh,0) bhs from chinese
select nvl(bh,0) bhs from chinese
从表中随机返回 n 条记录
实现此功能需要使用函数 ()作为 order by 子句的参数,
这样查询将依赖于函数的结果进行排序。利用这个函数可以实现随机出题
例 1:随机产生 100 条歇后语记录
Select *
from (
select xh,content,keys from xhy order by ()
)
Where rownum<=100;
例 2:利用函数 ()产生 100 个随机数
Oracle 10g 方法
select () from dual connect by rownum<=100
Oracle 9i 方法
select () from all_objects rownum<=100
根据学生成绩排名次
要求:要求输出前 n 名学生,同一成绩名次相同。
原理:利用 dense_rank()这个分析函数进行名次排列
主要数据如下
Xm score
c 72
x 83
b 83
d 65
h 96
n 57
y 90
m 99
v 100
输出前 5 名
Xm score mc
n 57 1
d 65 2
c 72 3
x 83 4
b 83 4
y 90 5
select * from(
select xm,score,dense_rank()over(order by score) mc from studentscore t
)
where mc<=5
oracle 使用 merge 更新或插入数据
使用 merge 比传统的先判断再选择插入或更新快很多。
1)主要功能
提供有条件地更新和插入数据到数据库表中
如果该行存在,执行一个 UPDATE 操作,如果是一个新行,执行 INSERT 操作
— 避免了分开更新
— 提高性能并易于使用
— 在数据仓库应用中十分有用
2)MERGE 语句的语法如下:
MERGE [hint] INTO [schema .] table [t_alias] USING [schema .]
{ table | view | subquery } [t_alias] ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
还是看例子就知道怎么回事:
MERGE INTO copy_emp c
USING employees e
ON (_id=_id)
WHEN MATCHED THEN
UPDATE SET
_name=_name,
_name=_name,
_id=_id
WHEN NOT MATCHED THEN
INSERT VALUES(_id,_name,_name,
,_number,_date,_id,
,_pct,_id,
_id);
MERGE INTO copy_emp c
USING employees e
ON (_id=_id)
WHEN MATCHED THEN
UPDATE SET
_name=_name,
_name=_name,
_id=_id
WHEN NOT MATCHED THEN
INSERT VALUES(_id,_name,_name,
,_number,_date,_id,
,_pct,_id,
_id);
3)使用 merge 的注意事项:
创建测试表:
CREATE TABLE MM (ID NUMBER, NAME VARCHAR2(20));
CREATE TABLE MN (ID NUMBER, NAME VARCHAR2(20));
插入数据
INSERT INTO MM VALUES (1, 'A');
INSERT INTO MN VALUES (1, 'B');
执行:
MERGE INTO MN A
USING MM B
ON(=)
WHEN MATCHED THEN
UPDATE SET =
WHEN NOT MATCHED THEN
INSERT VALUES(, );
ON(=)
报错:无效的标识符,这个错误提示有些误导嫌疑,原因是 on 子句的使用的字段不能够用于
update,即 Oracle 不允许更新用于连接的列
修改:
MERGE INTO MN A
USING MM B
ON(=)
WHEN MATCHED THEN
UPDATE SET =
WHEN NOT MATCHED THEN
INSERT VALUES(, );
ON(=)
再插入:INSERT INTO MM VALUES (1, 'C');
再执行:
MERGE INTO MN A
USING MM B
ON(=)
WHEN MATCHED THEN
UPDATE SET =
WHEN NOT MATCHED THEN
INSERT VALUES(, );
ON(=)
报错,原因无法在源表中获得一组稳定的行
4)更新同一张表的数据。需要注意下细节,因为可能涉及到 using 的数据集为 null,所以要
使用 count()函数。
MERGE INTO mn a
USING (select count(*) co from mn where =4) b
ON (<>0)--这里使用了 count 和<>,注意下,想下为什么!
WHEN MATCHED THEN
UPDATE
SET = 'E'
where =4
WHEN NOT MATCHED THEN
INSERT
VALUES (4, 'E');
计算中位(间)值
一、问题
计算一列数字值的中间值(中间值就是一组有序元素中间成员的值)。
假设有如下数据:
create table empInfo
(
name varchar2(20),
sal number(6)
)
insert into empInfo values('王宏',800);
insert into empInfo values('留心会',1100);
insert into empInfo values('张三',1500);
insert into empInfo values('李薇霞',3000);
insert into empInfo values('大大村',2500);
insert into empInfo values('杨伟',2750);
select * from empInfo order by sal
王宏 800
留心会 1100
张三 1500
大大村 2500
杨伟 2750
李薇霞 3000
中位数应为:2000=(1500+2500)/2
二、解决方案
除了 Oracle 解决方案(用函数计算中间数)之外,其他所有解决方案都是以 Rozenshtein、
Abramovich 和 Birger 在 Optimizing Transact-SQL: Advanced Programming Techniques (SQL
Forum Press, 1997)中描述的方法为基础的。与传统的自联接相比,窗口函数的引入,使解决
方案更为有效。
1. 通用求中位数的方法
使用自联接查找中间数:其原理是:
首先进行自连接,获得笛卡尔积;其次计算各记录 sal 字段的差并转换为符号函数,
即:sign( - )以及各个记录 sal 字段是否相同,用下列语句实现:
case when = then 1 else 0 end;然后再进行分组,并计算组内 sal 字段的平均值。
如果一列数为奇数个数,则这列数必定关于中间一个数的 abs(sum(sign( - )))成对
称。如果一列数为偶数个数,则这列数必定关于中间的两个数成对称。
select avg(sal) from (
--找到中间位置的sal值
select
from empInfo e, empInfo d
group by
having sum(
case when = then 1 else 0 end
)>= abs(sum(sign( - )))--end abs
)t
根据第一个自联接表 EMP 计算中间数,而该表返回了所有工资的笛卡儿积(GROUP
BY 会去掉重复值)。HAVING 子句使用函数 SUM 计算 等于 的次数;
如果这个值大于等于 且大于 次数,那么该行就是中间数。在 SELECT 列表中
加入 SUM 就可以观察到这种情况:
select avg(sal) from (
--找到中间位置的sal值
select ,count() ncount,
sum(case when = then 1 else 0 end) sum0,
abs(sum(sign( - )) ) abs0
from empInfo e, empInfo d
group by
having sum(
case when = then 1 else 0 end
)>= abs(sum(sign( - )))--end abs
)t
800 7 1 6
1100 7 1 4
1500 7 1 2
2200 7 1 0
2500 7 1 2
2750 7 1 4
3000 7 1 6
,Oracle 数据库
使用窗口函数 COUNT(*) OVER 和 ROW_NUMBER,查找中间数:
select avg(sal) from(
--通过分析函数为查询添加 3 列:total,half,xh
select sal,
count(*) over() total,
floor(count(*) over()/2) half,
row_number() over(order by sal) xh
from empInfo
)
where (mod(total,2)=0 and xh in(half,half+1))—偶数行,取中间两行的值
or (mod(total,2)=1 and xh=half+1) —奇数行,取中间行的值
执行结果:
2000===(1500+2500)/2
数据库
使用函数 MEDIAN(Oracle Database 10g)或 PERCENTILE_CONT(Oracle9i 及以上版
本):
--使用于 Oracle10g 及以上版本
select median(sal) from empInfo
--使用于 Oracle9i 及以上版本
select percentile_cont()
within group(order by sal)
from empInfo
说明:对于 Oracle8i Database,使用 DB2 解决方案。对于 Oracle8i Database 之前的版本,可
以采用 PostgreSQL/MySQL 解决方案。
Server 数据库(sqlserver2005 以上版本)
使用窗口函数 COUNT(*) OVER 和 ROW_NUMBER,可得到中间数:
--创建数据表
create table empInfo
(
name varchar(20),
sal int
)
--向表插入数据
insert into empInfo values('王宏',800);
insert into empInfo values('留心会',1100);
insert into empInfo values('张三',1500);
insert into empInfo values('李薇霞',3000);
insert into empInfo values('大大村',2500);
insert into empInfo values('杨伟',2750);
insert into empInfo values('华阳',2200);
--查询
select * from empInfo order by sal
王宏 800
留心会 1100
张三 1500
华阳 2200
大大村 2500
杨伟 2750
李薇霞 3000
--获得中位数
select avg(sal) from(
select sal,
count(*) over() total,
floor(count(*) over()/2) half,
row_number() over(order by sal) xh
from empInfo
) t
where (xh %2=0 and xh in(half,half+1))--偶数行,取中间两行的值
or (xh % 2=1 and xh=half+1) --数行,取中间行的值
三、各种方案总结
和 SQL Server 解决方案的唯一差别是语法的稍许不同:SQL Server 用“%”求模,
而 DB2 和 Oracle 使用 MOD 函数;其余的都相同。
2.内联视图 X 返回三个不同的计数值,TOTAL 和 halfT,还用到由 ROW_NUMBER 生
成的 RN。这些附加列有助于求解中间数。检验内联视图 X 的结果集,就会看到这些列表示
的意义:
3.根据第一个自联接表 EMP 计算中间数,而该表返回了所有工资的笛卡儿积(GROUP
BY 会去掉重复值)。HAVING 子句使用函数 SUM 计算 等于 的次数;
如果这个值大于等于 且大于 次数,那么该行就是中间数。在 SELECT 列表中
加入 SUM 就可以观察到这种情况:
--找到中间位置的sal值
select ,count() ncount,
sum(case when = then 1 else 0 end) sum0,
abs(sum(sign( - )) ) abs0
from empInfo e, empInfo d
group by
Oracle
在 Oracle Database 10g 或 Oracle9i Database 中,可以使用 Oracle 提供的函数计算中间数;对
于 Oracle8i Database,可以采用 DB2 解决方案;其他版本只能采用通用求中位数的解决方案。
显然可以用 MEDIAN 函数计算中间值,用 PERCENTILE_CONT 函数也可以计算中间值
就不那么显而易见了。传递给 PERCENTILE_CONT 的值 是一个百分比值。子句 WITHIN
GROUP (ORDER BY SAL)确定 PERCENTILE_CONT 要搜索哪些有序行(记住,中间值就
是一组已排序值的中间值)。返回的值就是搜索的有序行中符合给定百分比(在这个例子中
是 ,因为其两个边界值分别为 0 和 1)的值。
总之,通用解决方案适用于各种版本各种类型的数据库,但效率较低;
Oracle 提供了响应的函数,但对版本要求较高;Sqlserver 和 Oracle 一样,对版本有要求。
计算众数的方法
一、准备数据
select * from tb
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
刘洋 语文 81
刘洋 数学 82
刘洋 物理 86
二、求众数的一般方法:
--首先构造CTE
with tbGroup as
(select xm,count(*) total from tb group by xm)
--找出具有最大值的所有记录(即众数)
方案1:
select * from tbGroup
where total=(
select max(total) from tbGroup –求各组内的最大值
)
显示结果:
刘洋 3
张三 3
方案 2:
select * from (
select xm,total,dense_rank() over(order by total desc) mc from tbGroup
)t
where mc=1
显示结果:
刘洋 3 1
张三 3 1
即该组数中有 2 个众数。注意:一组数可能没有众数!此时 CTE 将返回空集!
查询出连续的记录
有一个表结构,fphm,kshm,其记录如下:
2014,00000001
2014,00000002
2014,00000003
2014,00000004
2014,00000005
2014,00000007
2014,00000008
2014,00000009
2013,00000120
2013,00000121
2013,00000122
2013,00000124
2013,00000125
(第二个字段内可能是连续的数据,可能存在断点。)
要求查询出连续的记录来。就像下面的这样?
2014,00000001,00000005
2014,00000009,00000007
2013,00000120,00000122
2013,00000124,00000125
SELECT , MIN () Start_HM, MAX () End_HM
FROM (
SELECT a.*, TO_NUMBER ( - ROWNUM) cc
FROM (SELECT * FROM t ORDER BY fphm, kshm) a
) b
GROUP BY ,
SELECT , MIN () Start_HM, MAX () End_HM
FROM (
SELECT a.*, TO_NUMBER ( - ROWNUM) cc FROM (
SELECT * FROM t ORDER BY fphm, kshm
) a
) b
GROUP BY ,
FPHM START_HM END_HM
---------- -------- --------
2013 00000120 00000122
2013 00000124 00000125
2014 00000001 00000005
2014 00000007 00000009
//////////////////////////////////////////////////////////////////////////////////////////////
查询所有物品的最后出库时间
物品 出库时间
a 2005-3-4
a 2005-12-3
a 2006-10-8
a 2007-5-1
b 2006-1-1
b 2006-10-2
b 2007-6-24
c 2006-12-2
c 2007-3-8
------------------------
要求结果
物品 最后出库时间
a 2007-5-1
b 2007-6-24
c 2007-3-8
select mc,max(rq) from SQLnumber group by mc
select * from SQLnumber as a
where exists (
select top 1 * from SQLnumber as b where = order by rq desc
)
select * from [table] as a exits (select top 1 * from [table] as b where [b].[物品]=[a].[物品] order
by [出库时间] desc)
农历】计算方法--- (阳历转阴历)
因为农历的日期,是由天文学家推算出来的,到现在只有到 2049 年的,以后的有了还
可以加入!首先建一表,放初始化资料
1.创建表
CREATE TABLE SolarData
(
yearId int not null,
data char(7) not null,
dataInt int not null
)
2.插入数据
INSERT INTO
SolarData SELECT 1900,'0x04bd8',19416 UNION ALL SELECT 1901,'0x04ae0',19168
UNION ALL SELECT 1902,'0x0a570',42352 UNION ALL SELECT 1903,'0x054d5',21717
UNION ALL SELECT 1904,'0x0d260',53856 UNION ALL SELECT 1905,'0x0d950',55632
UNION ALL SELECT 1906,'0x16554',91476 UNION ALL SELECT 1907,'0x056a0',22176
UNION ALL SELECT 1908,'0x09ad0',39632 UNION ALL SELECT 1909,'0x055d2',21970
UNION ALL SELECT 1910,'0x04ae0',19168 UNION ALL SELECT 1911,'0x0a5b6',42422
UNION ALL SELECT 1912,'0x0a4d0',42192 UNION ALL SELECT 1913,'0x0d250',53840
UNION ALL SELECT 1914,'0x1d255',119381 UNION ALL SELECT 1915,'0x0b540',46400
UNION ALL SELECT 1916,'0x0d6a0',54944 UNION ALL SELECT 1917,'0x0ada2',44450
UNION ALL SELECT 1918,'0x095b0',38320 UNION ALL SELECT 1919,'0x14977',84343
UNION ALL SELECT 1920,'0x04970',18800 UNION ALL SELECT 1921,'0x0a4b0',42160
UNION ALL SELECT 1922,'0x0b4b5',46261 UNION ALL SELECT 1923,'0x06a50',27216
UNION ALL SELECT 1924,'0x06d40',27968 UNION ALL SELECT 1925,'0x1ab54',109396
UNION ALL SELECT 1926,'0x02b60',11104 UNION ALL SELECT 1927,'0x09570',38256
UNION ALL SELECT 1928,'0x052f2',21234 UNION ALL SELECT 1929,'0x04970',18800
UNION ALL SELECT 1930,'0x06566',25958 UNION ALL SELECT 1931,'0x0d4a0',54432
UNION ALL SELECT 1932,'0x0ea50',59984 UNION ALL SELECT 1933,'0x06e95',28309
UNION ALL SELECT 1934,'0x05ad0',23248 UNION ALL SELECT 1935,'0x02b60',11104
UNION ALL SELECT 1936,'0x186e3',100067 UNION ALL SELECT 1937,'0x092e0',37600
UNION ALL SELECT 1938,'0x1c8d7',116951 UNION ALL SELECT 1939,'0x0c950',51536
UNION ALL SELECT 1940,'0x0d4a0',54432 UNION ALL SELECT 1941,'0x1d8a6',120998
UNION ALL SELECT 1942,'0x0b550',46416 UNION ALL SELECT 1943,'0x056a0',22176
UNION ALL SELECT 1944,'0x1a5b4',107956 UNION ALL SELECT 1945,'0x025d0',9680
UNION ALL SELECT 1946,'0x092d0',37584 UNION ALL SELECT 1947,'0x0d2b2',53938
UNION ALL SELECT 1948,'0x0a950',43344 UNION ALL SELECT 1949,'0x0b557',46423
UNION ALL SELECT 1950,'0x06ca0',27808 UNION ALL SELECT 1951,'0x0b550',46416
UNION ALL SELECT 1952,'0x15355',86869 UNION ALL SELECT 1953,'0x04da0',19872
UNION ALL SELECT 1954,'0x0a5d0',42448 UNION ALL SELECT 1955,'0x14573',83315
UNION ALL SELECT 1956,'0x052d0',21200 UNION ALL SELECT 1957,'0x0a9a8',43432
UNION ALL SELECT 1958,'0x0e950',59728 UNION ALL SELECT 1959,'0x06aa0',27296
UNION ALL SELECT 1960,'0x0aea6',44710 UNION ALL SELECT 1961,'0x0ab50',43856
UNION ALL SELECT 1962,'0x04b60',19296 UNION ALL SELECT 1963,'0x0aae4',43748
UNION ALL SELECT 1964,'0x0a570',42352 UNION ALL SELECT 1965,'0x05260',21088
UNION ALL SELECT 1966,'0x0f263',62051 UNION ALL SELECT 1967,'0x0d950',55632
UNION ALL SELECT 1968,'0x05b57',23383 UNION ALL SELECT 1969,'0x056a0',22176
UNION ALL SELECT 1970,'0x096d0',38608 UNION ALL SELECT 1971,'0x04dd5',19925
UNION ALL SELECT 1972,'0x04ad0',19152 UNION ALL SELECT 1973,'0x0a4d0',42192
UNION ALL SELECT 1974,'0x0d4d4',54484 UNION ALL SELECT 1975,'0x0d250',53840
UNION ALL SELECT 1976,'0x0d558',54616 UNION ALL SELECT 1977,'0x0b540',46400
UNION ALL SELECT 1978,'0x0b5a0',46496 UNION ALL SELECT 1979,'0x195a6',103846
UNION ALL SELECT 1980,'0x095b0',38320 UNION ALL SELECT 1981,'0x049b0',18864
UNION ALL SELECT 1982,'0x0a974',43380 UNION ALL SELECT 1983,'0x0a4b0',42160
UNION ALL SELECT 1984,'0x0b27a',45690 UNION ALL SELECT 1985,'0x06a50',27216
UNION ALL SELECT 1986,'0x06d40',27968 UNION ALL SELECT 1987,'0x0af46',44870
UNION ALL SELECT 1988,'0x0ab60',43872 UNION ALL SELECT 1989,'0x09570',38256
UNION ALL SELECT 1990,'0x04af5',19189 UNION ALL SELECT 1991,'0x04970',18800
UNION ALL SELECT 1992,'0x064b0',25776 UNION ALL SELECT 1993,'0x074a3',29859
UNION ALL SELECT 1994,'0x0ea50',59984 UNION ALL SELECT 1995,'0x06b58',27480
UNION ALL SELECT 1996,'0x055c0',21952 UNION ALL SELECT 1997,'0x0ab60',43872
UNION ALL SELECT 1998,'0x096d5',38613 UNION ALL SELECT 1999,'0x092e0',37600
UNION ALL SELECT 2000,'0x0c960',51552 UNION ALL SELECT 2001,'0x0d954',55636
UNION ALL SELECT 2002,'0x0d4a0',54432 UNION ALL SELECT 2003,'0x0da50',55888
UNION ALL SELECT 2004,'0x07552',30034 UNION ALL SELECT 2005,'0x056a0',22176
UNION ALL SELECT 2006,'0x0abb7',43959 UNION ALL SELECT 2007,'0x025d0',9680
UNION ALL SELECT 2008,'0x092d0',37584 UNION ALL SELECT 2009,'0x0cab5',51893
UNION ALL SELECT 2010,'0x0a950',43344 UNION ALL SELECT 2011,'0x0b4a0',46240
UNION ALL SELECT 2012,'0x0baa4',47780 UNION ALL SELECT 2013,'0x0ad50',44368
UNION ALL SELECT 2014,'0x055d9',21977 UNION ALL SELECT 2015,'0x04ba0',19360
UNION ALL SELECT 2016,'0x0a5b0',42416 UNION ALL SELECT 2017,'0x15176',86390
UNION ALL SELECT 2018,'0x052b0',21168 UNION ALL SELECT 2019,'0x0a930',43312
UNION ALL SELECT 2020,'0x07954',31060 UNION ALL SELECT 2021,'0x06aa0',27296
UNION ALL SELECT 2022,'0x0ad50',44368 UNION ALL SELECT 2023,'0x05b52',23378
UNION ALL SELECT 2024,'0x04b60',19296 UNION ALL SELECT 2025,'0x0a6e6',42726
UNION ALL SELECT 2026,'0x0a4e0',42208 UNION ALL SELECT 2027,'0x0d260',53856
UNION ALL SELECT 2028,'0x0ea65',60005 UNION ALL SELECT 2029,'0x0d530',54576
UNION ALL SELECT 2030,'0x05aa0',23200 UNION ALL SELECT 2031,'0x076a3',30371
UNION ALL SELECT 2032,'0x096d0',38608 UNION ALL SELECT 2033,'0x04bd7',19415
UNION ALL SELECT 2034,'0x04ad0',19152 UNION ALL SELECT 2035,'0x0a4d0',42192
UNION ALL SELECT 2036,'0x1d0b6',118966 UNION ALL SELECT 2037,'0x0d250',53840
UNION ALL SELECT 2038,'0x0d520',54560 UNION ALL SELECT 2039,'0x0dd45',56645
UNION ALL SELECT 2040,'0x0b5a0',46496 UNION ALL SELECT 2041,'0x056d0',22224
UNION ALL SELECT 2042,'0x055b2',21938 UNION ALL SELECT 2043,'0x049b0',18864
UNION ALL SELECT 2044,'0x0a577',42359 UNION ALL SELECT 2045,'0x0a4b0',42160
UNION ALL SELECT 2046,'0x0aa50',43600 UNION ALL SELECT 2047,'0x1b255',111189
UNION ALL SELECT 2048,'0x06d20',27936 UNION ALL SELECT 2049,'0x0ada0',44448
3.创建存储过程:
.转换阿拉伯数字为汉字数字
CREATE FUNCTION [dbo].[f_num_str] (@num int)
RETURNS varchar(100)
AS
BEGIN
DECLARE @n_str VARCHAR(20),@re VARCHAR(20),@i int
SELECT @n_str=cast(@num as varchar),@i=1,@re=''
WHILE @i<=len(@n_str)
BEGIN
SET @re=@re+SUBSTRING('零一二三四五六七八九',CAST(SUBSTRING(@n_str,@i,1) AS
int)+1,1)
SET @i=@i+1
END
RETURN @re
END
. 根据阳历返回对应的阴历
CREATE PROCEDURE GetLunar_zhangzs
@solarDay DATETIME --日期
AS
DECLARE @solData int
DECLARE @offset int
DECLARE @iLunar int
DECLARE @i INT
DECLARE @j INT
DECLARE @yDays int
DECLARE @mDays int
DECLARE @mLeap int
DECLARE @mLeapNum int
DECLARE @bLeap smallint
DECLARE @temp int
DECLARE @YEAR INT
DECLARE @MONTH INT
DECLARE @DAY INT
DECLARE @OUTPUTDATE varchar(10)
--保证传进来的日期是不带时间
SET @solarDay=cast(@solarDay AS char(10))
SET @offset=CAST(@solarDay-'1900-01-30' AS INT)
--确定农历年开始
SET @i=1900
--SET @offset=@solData
WHILE @i<2050 AND @offset>0
BEGIN
SET @yDays=348
SET @mLeapNum=0
--根据年id 获得对应的datInt值
SELECT @iLunar=dataInt FROM SolarData WHERE yearId=@i
--传回农历年的总天数
SET @j=32768
WHILE @j>8
BEGIN
IF @iLunar & @j >0
SET @yDays=@yDays+1
SET @j=@j/2
END
--传回农历年闰哪个月1-12 , 没闰传回0
SET @mLeap = @iLunar & 15
--传回农历年闰月的天数,加在年的总天数上
IF @mLeap > 0
BEGIN
IF @iLunar & 65536 > 0
SET @mLeapNum=30
ELSE
SET @mLeapNum=29
SET @yDays=@yDays+@mLeapNum
END
SET @offset=@offset-@yDays
SET @i=@i+1
END
IF @offset <= 0
BEGIN
SET @offset=@offset+@yDays
SET @i=@i-1
END
--确定农历年结束
SET @YEAR=@i
--确定农历月开始
SET @i = 1
SELECT @iLunar=dataInt FROM SolarData WHERE yearId=@YEAR
--判断那个月是润月
SET @mLeap = @iLunar & 15
SET @bLeap = 0
WHILE @i < 13 AND @offset > 0
BEGIN
--判断润月
SET @mDays=0
IF (@mLeap > 0 AND @i = (@mLeap+1) AND @bLeap=0)
BEGIN--是润月
SET @i=@i-1
SET @bLeap=1
--传回农历年闰月的天数
IF @iLunar & 65536 > 0
SET @mDays = 30
ELSE
SET @mDays = 29
END
ELSE
--不是润月
BEGIN
SET @j=1
SET @temp = 65536
WHILE @j<=@i
BEGIN
SET @temp=@temp/2
SET @j=@j+1
END
IF @iLunar & @temp > 0
SET @mDays = 30
ELSE
SET @mDays = 29
END
--解除闰月
IF @bLeap=1 AND @i= (@mLeap+1)
SET @bLeap=0
SET @offset=@offset-@mDays
SET @i=@i+1
END
IF @offset <= 0
BEGIN
SET @offset=@offset+@mDays
SET @i=@i-1
END
--确定农历月结束
SET @MONTH=@i
--确定农历日结束
SET @DAY=@offset
SET @OUTPUTDATE=convert(varchar(10),CAST((CAST(@YEAR AS VARCHAR(4))+'-'+CAST(@MONTH
AS VARCHAR(2))+'-'+CAST(@DAY AS VARCHAR(2))) AS DATETIME) ,120)
select convert( varchar(10),@solarDay ,120) as 阳历
,cast(_num_str(year(@OUTPUTDATE)) as varchar(8))+'年|' +
case when datalength(_num_str(month(@OUTPUTDATE)))=4 then case when
left(_num_str(month(@OUTPUTDATE)),1)<>'一'
then left(month(@OUTPUTDATE),1) else '' end + '十'+ case when
right(_num_str(month(@OUTPUTDATE)),1)='零' then '' else
right(_num_str(month(@OUTPUTDATE)),1) end else
cast(_num_str(month(@OUTPUTDATE)) as varchar(4)) end +'月|'
+ case when datalength(_num_str(day(@OUTPUTDATE)))=4 then case when
cast(_num_str(day(@OUTPUTDATE) )as varchar(4))='一零'then '初' else (case when
left(cast(_num_str(day(@OUTPUTDATE) )as varchar(4)),1)<>'一'
then left(cast(_num_str(day(@OUTPUTDATE) )as varchar(4)),1) else '' end)end +'十'+ case when
right(cast(_num_str(day(@OUTPUTDATE) )as varchar(4)),1)='零' then '' else
right(cast(_num_str(day(@OUTPUTDATE) )as varchar(4)),1)end else '初'
+cast(_num_str(day(@OUTPUTDATE) )as varchar(4)) end as 阴历
GO
--调用存储过程
exec GetLunar_zhangzs '2010-02-28'
--返回结果:
阳历 阴历
---------- --------------------------
2010-02-28 二零一零年|一月|十五 --正月十五(元宵节)
干支计算方法
1.干支相关类型定义:
CREATE OR REPLACE Type gzType as object
(
id number(3),
gz nchar(2)
)
CREATE OR REPLACE Type gzTableType as table of gzType
2.干支计算方法 1:
create or replace function getGzData
return gzTableType PIPELINED --将管道与一个 table 对象 MsgType 关联
as
Type myTg is varray(10) of nchar(1);
Type myDz is varray(12) of nchar(1);
tg myTg:=myTg('甲','乙','丙','丁','戊','己','庚','辛','壬','癸');
dz myDz:=myDz('子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥');
indexTg integer:=0;
indexDz integer:=0;
t nchar(2);
begin
for i in 1 .. 60 loop
t:=tg(indexTg+1) || dz(indexDz+1);
pipe row(gzType(i,t));
indexTg:=mod((indexTg+1),10); --调整天干索引
indexDz:=mod((indexDz+1),12); --调整地支索引
end loop;
return; --必须返回'空'
end;
3.干支计算方法 2:
create or replace function getGzData2
return gzTableType
as
Type myTg is varray(10) of nchar(1);
Type myDz is varray(12) of nchar(1);
tg myTg:=myTg('甲','乙','丙','丁','戊','己','庚','辛','壬','癸');
dz myDz:=myDz('子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥');
indexTg integer:=0;
indexDz integer:=0;
t nchar(2);
v_result gzTableType:=gzTableType(); --实例化对象
begin
for i in 1 .. 60 loop
t:=tg(indexTg+1) || dz(indexDz+1);
--pipe row(gzType(i,t));
-- 增加的元素赋值,如果没用 EXTEND,这里会出错
(); --增加一个元素
v_result() := gzType(i,t); --为新增加的元素赋值
indexTg:=mod((indexTg+1),10); --调整天干索引
indexDz:=mod((indexDz+1),12); --调整地支索引
end loop;
return v_result; --必须返回
end;
oracle10g 实现把汉字转换成汉语拼音首字母
第一步、创建 java 源
create or replace and resolve java source named "hz2py"
as public class hz2py {
public static int compare(string str1, string str2)
{
int result = 0;
string m_s1 = null;
string m_s2 = null;
try
{
m_s1 = new string((_fromencode_), _toencode_);
m_s2 = new string((_fromencode_), _toencode_);
}
catch(exception e)
{
return (str2);
}
result = chinesecompareto(m_s1, m_s2);
return result;
}
public static int getcharcode(string s)
{
if(s == null && (""))
return -1;
byte b[] = ();
int value = 0;
for(int i = 0; i < && i <= 2; i++)
value = value * 100 + b[i];
return value;
}
public static int chinesecompareto(string s1, string s2)
{
int len1 = ();
int len2 = ();
int n = (len1, len2);
for(int i = 0; i < n; i++)
{
int s1_code = getcharcode((i) + "");
int s2_code = getcharcode((i) + "");
if(s1_code * s2_code < 0)
return (s1_code, s2_code);
if(s1_code != s2_code)
return s1_code - s2_code;
}
return len1 - len2;
}
public static string getbegincharacter(string res)
{
string a = res;
string result = "";
for(int i = 0; i < (); i++)
{
string current = (i, i + 1);
if(compare(current, "\u554a") < 0)
result = result + current;
else
if(compare(current, "\u554a") >= 0 && compare(current, "\u5ea7") <= 0)
if(compare(current, "\u531d") >= 0)
result = result + "z";
else
if(compare(current, "\u538b") >= 0)
result = result + "y";
else
if(compare(current, "\u6614") >= 0)
result = result + "x";
else
if(compare(current, "\u6316") >= 0)
result = result + "w";
else
if(compare(current, "\u584c") >= 0)
result = result + "t";
else
if(compare(current, "\u6492") >= 0)
result = result + "s";
else
if(compare(current, "\u7136") >= 0)
result = result + "r";
else
if(compare(current, "\u671f") >= 0)
result = result + "q";
else
if(compare(current, "\u556a") >= 0)
result = result + "p";
else
if(compare(current, "\u54e6") >= 0)
result = result + "o";
else
if(compare(current, "\u62ff") >= 0)
result = result + "n";
else
if(compare(current, "\u5988") >= 0)
result = result + "m";
else
if(compare(current, "\u5783") >= 0)
result = result + "l";
else
if(compare(current, "\u5580") >= 0)
result = result + "k";
else
if(compare(current, "\u51fb") > 0)
result = result + "j";
else
if(compare(current, "\u54c8") >= 0)
result = result + "h";
else
if(compare(current, "\u5676") >= 0)
result = result + "g";
else
if(compare(current, "\u53d1") >= 0)
result = result + "f";
else
if(compare(current, "\u86fe") >= 0)
result = result + "e";
else
if(compare(current, "\u642d") >= 0)
result = result + "d";
else
if(compare(current, "\u64e6") >= 0)
result = result + "c";
else
if(compare(current, "\u82ad") >= 0)
result = result + "b";
else
if(compare(current, "\u554a") >= 0)
result = result + "a";
}
return result;
}
private static string _fromencode_ = "gbk";
private static string _toencode_ = "gbk";
}
/
第二步、创建函数使用 java 类
create or replace
function f_hz2py(name varchar2) return varchar2
as language java name
'() return ';
/
select f_hz2py('美国鬼子,小日本') from dual;
返回 mggz,xrb
以上给出了扩展 oracle 自身提供功能的一种方法。同行们可以把 java 类转化为函数函数,供 pl/sql 调用。
java 源被 oracle8i 以上版本支持。oracle8i 以上版本,可以把 java 源看作 view、proc、table 等对 oracle
对象一样
Oracle 10g 中利用哈希函数提高查询速度
2007-04-02 14:27 bensiyuan 赛迪网技术社区 我要评论(0)
摘要:本文通过一个信用卡业务的数据库来介绍如何建立建立一个簇表,使用一个哈希函数来约
束簇块的数量,以及如何在进行每个查询操作时使用排序哈希簇。
标签:哈希 函数 簇 Oracle 10g
Oracle 帮您准确洞察各个物流环节
当数据存储在一个普通表中的时候,这些记录将以插入到数据库时的顺序物理地保存到
分配的块中。例如,如果有一个用于存储员工信息的表,那么员工姓名将会按照插入到表的
顺序存储在表中。
如果员工记录非常多的话,那么数据表的响应速度就会逐渐变慢。你可以通过选择值相
对等分布的一列(如员工的部门编号)并建立一个簇表来提高查询员工的速度。
在簇表中,如果员工属于同一个部门,那么它们的记录将物理地存储在同一系列的块中。
这样就可以提高查找员工信息的速度,这是因为在检索某个特定部门的员工时,需要读取数
据库块的数量减少了。而在非簇表中查找员工,就可能需要对每个数据库块进行访问。
当表中存在大量键值的时候,你就会开始发现由于存在许多簇块而导致的性能问题。避
免这个问题的一个方法就是使用一个哈希函数来约束簇块的数量。哈希函数将会给定一个数
值用来限定簇块数量的预计范围,但它得到的值是相对等分布的。例如你可以创建一个哈希
函数,只比较部门编号的最后两位。
哈希函数中存在的一个问题就是函数值会打乱记录原本的顺序。你可以通过 ORDER
BY 来解决这个问题;但是,在很多情况下,记录数量是非常庞大的。在 Oracle 10g 中,你
可以将一个数据定义为“natural order” ,那么就可以不用经过排序而以你所希望的顺序来检
索哈希簇的数据,从而解决了上面的提出问题。
例如,假设你有一个信用卡业务的数据库。你决定以信用卡号作为簇主键将有利于数据
的存储分布。但是,由于存在大量的信用卡号,所以可以使用一个哈希函数来约束簇块的数
量。而且你希望在你的大部分报表中数据是按照时间顺序排列的,那么在进行每个查询操作
时使用排序哈希簇,而不要使用 ORDER BY。下面给出了相关语句:
create cluster credit_cluster
(
card_no varchar2(16),
transdate date sort
)
hashkeys 10000 hash is ora_hash(card_no)
size 256;
create table credit_orders
(
card_no varchar2(16),
transdate date,
amount number
)
cluster credit_cluster(card_no,transdate);
alter session set nls_date_format = "YYYYMMDDHH24MISS";
insert into credit_orders (card_no,transdate,amount)
values ('4111111111111111','20050131000123',);
insert into credit_orders (card_no,transdate,amount)
values ('4111111111111111','20050130071216',);
insert into credit_orders (card_no,transdate,amount)
values ('4111111111111111','20050131111111',);
insert into credit_orders (card_no,transdate,amount)
values ('4111111111111111','20050130081001',);
可以看到我在这里使用了一个新函数 ORA_HASH 来为信用卡建立一个哈希数值。现在,
你可以非常简单地对某个信用卡数据进行查询,并返回自动排序后的结果。