|
|
2008年9月2日
当我们获取数据时,可能会有这样的需求,即每次从表中获取数据时,是随机获取一定的记录,而不是每次都获取一样的数据,这时我们可以采取Oracle内部一些函数,来达到这样的目的.
1) select * from (select * from tablename order by sys_guid()) where rownum < N;
2) select * from (select * from tablename order by dbms_random.value) where rownum< N;
3) select * from (select * from table_name sample(10) order by trunc(dbms_random.value(0, 1000))) where rownum < N;
说明: sample(10)含义为检索表中的10%数据,sample值应该在[0.000001,99.999999]之间.
其中 sys_guid() 和 dbms_random.value都是内部函数,通过这样的方法,就可以实现我们的需求了.
注:
在使1)方法时,即使用sys_guid() 这种方法时,有时会获取到相同的记录,即和前一次查询的结果集是一样的,我查找了相关资料,有些说是和操作系统有关,在windows平台下正常,获取到的数据是随机的,而在linux等平台下始终是相同不变的数据集,有些说是因为sys_guid()函数本身的问题,即sys_guid()会在查询上生成一个16字节的全局唯一标识符,这个标识符在绝大部分平台上由一个宿主标识符和进程或进程的线程标识符组成,这就是说,它很可能是随机的,但是并不表示一定是百分之百的这样.
所以,为确保在不同的平台每次读取的数据都是随机的,我们大多采用2)和3)两种方案,其中2)方案更常用.3)方案缩小了查询的范围,在查询大表,且要提取数据不是很不多的情况下,会对查询速度上有一定的提高,
另:在Oracle中一般获取随机数的方法是:
select trunc(dbms_random.value(0, 1000)) from dual; (0-1000的整数)
select dbms_random.value(0, 1000) from dual; (0-1000的浮点数)
2008年8月29日
当我们要在Eclipse下要快速调试Web应用程序时,可以给 Eclipse安装TomcatPlugin插件,这样就可以快速的启动和关闭Tomcat了,调试程序起来快捷了很多,而且又比MyEclipse容量小了很多(当然功能和它没法比),但当我们不需要那么多功能时,我们只需给Eclipse安装个TomcatPlugin插件就可以了,但Eclipse和TomcatPlugin都有很多个不同的版本,而不同的版本需要对应所适应的版本,才能安装成功,否则总是安装失败的,这里提供一个链接,里面有各个对应的版本说明,我们可以根据本机的Eclipse版本下载相应的TomcatPlugin版本插件,
将TomcatPlugin插件下载下来后,解压放到your_Eclipse_Home/plugins,然后在命令行中用带-clean的参数启动Eclipse就可以了.
TomcatPlugin插件下载: http://www.eclipsetotale.com/tomcatPlugin.html
注:
1) 链接里面有很详细的安装说明,包括本已成功安装插件,但看不到小猫的情况;
2) 本人试过Eclipse3.2版本的TomcatPlugin插件安装,链接里面的各个版本都试过了,总是安装不上,不知道是什么原因,后来换成Eclipse3.3的一下子就安装成功了,对应的TomcatPlugin插件是tomcatPluginV321.zip,即同时试用于Eclipse3.1,Eclipse3.2,Eclipse3.3(链接里是这么说明的,但我用Eclipse3.2时,用此版本怎么都安装不成功,后来将Eclipse换成3.3的就可以了,呵呵).
3) 如果是Eclipse3.4,插件解应是放在your_Eclipse_Home/dropins下,且可以不带-clean参数,直接启动即可.
2008年8月27日
当我们跑一个 Struts2的小例子,如果使用的是Tomcat5.0.28.,则会报很多莫名其妙的错误,即便我们已经拷贝了那五个运行 Struts2的必须包,也还是会报错,今天在网上看到了一处理方法:
1.拷贝xalan目录下的xercesImpl.jar和xml-apis.jar替换掉Tomcat\common\endorsed下的两个jar文件。
2. 还需要将xalan下的xalan.jar和serializer.jar拷贝到Tomcat\common\lib中
当然可不可行,我还没试.
虽然现在Tomcat已经6.X了,但我觉得用Tomcat5.0.28的人应该还是会有很多的,必竟经典嘛,所以对于初学者想学习 Struts2的而少走些弯路的,可以参考下上面的方法.
另:
1) 我看了下Tomcat5.5的(5.5的可以直接跑,不存在5.0.28下那样的问题), 发现Tomcat\common\endorsed下没有任何JAR包,所以在Tomcat5.0.28下,删除Tomcat\common\endorsed下的JAR包或许也是可以的.
2) 那五个必须包是:
commons-logging-1.0.4.jar
ognl-2.6.11.jar
struts2-core-2.0.11.1.jar
freemarker-2.3.8.jar
xwork-2.0.4.jar
2008年8月21日
当我们已经创建好了一个存储过程,但发现创建的存储过程有问题时,我们需要修改此存储过程,以便数据库系统中存在一个我们所需要的正确的存储过程,有以下几种方法可以实现(是在命令行中进行操作,不是在PL/SQL中操作,在PL/SQL中操作问题就变得简单了):
1)先DROP PROC PROC_A,然后重新CREATE PROC PROC_A,但此时可能会有一个问题,即如果A存储过程已被其他存储过程引用,则此时将不能DROP 掉A存储过程,所以这样就产生了下面的方法;
2)直接ALTER PROC PROC_A,即修改存储过程A,这种方法的好处有:
修改以前用CREATE PROCEDURE 命令创建的存储过程,并且不改变权限的授予情况以及不影响任何其它的独立的存储过程或触发器,
ALTER PROC[EDURE] procedure_name [;number]
[ {@parameter data_type } [VARYING] [= default] [OUTPUT]] [,...n]
[WITH
{RECOMPILE │ ENCRYPTION │ RECOMPILE , ENCRYPTION}]
[FOR REPLICATION]
AS
sql_statement [...n]
3)用创建或存在就替换的命令进行操作,即 CREATE OR REPLACE PROCEDURE PROC_A.
另:查看存储过程内容(文本)
select text from all_source where OWNER='USERNAME' and TYPE='PROCEDURE' and NAME='PROCNAME';
经过查看内容后,就可以确认下存储过程是否是已经修改后的了.
2008年8月18日
2008年8月11日
from:http://www.blogjava.net/xcp/archive/2008/08/10/stack.html
堆和栈的区别
栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。
这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。
String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。
比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一次生成一个。
因此用第一种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。
由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。
2008年8月8日
我们一般在页面上填写比较多的数据时,一般用 textarea,但这时会有一个问题,即内容过多时,如何换行问题,也就是怎样让数据存入数据库及从数据库中读取到页面上显示时,与当初输入的格式一样,一般都是用如下的方法来解决:
//存入数据库
 public class Opera {

 public static String OperationChar(String message) {
 if (message == null) {
return null;
}
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
 for (int i = 0; i < content.length; i++) {
 switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
case ' ':
result.append(" ");
break;
case '\n':
result.append("<br/>");
break;
default :
result.append(content[i]);
}
}
return result.toString();
}
//显示在页面的时候
 public static String DEOperationChar(String message) {
 if(message ==null) {
return null;
}
StringBuffer result = new StringBuffer();
message.replaceAll("<", "<");
message.replaceAll("%gt;", ">");
message.replaceAll("&", "&");
message.replaceAll(""", "\"");
message.replaceAll(" ", " ");
return message;
}

}

注:上面用到几个方法:
1)void getChars(int sourceStart,int sourceEnd,char target[],int targetStart)
sourceStart指定了子串开始字符的下标,sourceEnd指定了子串结束后的下一个字符的下标。因此,子串包含从sourceStart到sourceEnd-1的字符。接收字符的数组由target指定,target中开始复制子串的下标值是targetStart。
例:String s="this is a demo of the getChars method.";
char buf[]=new char[20];
s.getChars(10,14,buf,0);
即将字符串的一部分或全部内容复制到一字符数组中
另:这里还用到了 StringBuffer,将 StringBuffer对象调用. toString()方法,即可做为字符串输出,如果要将得到的内容反转再输出,可以先调用. reverse()方法,再调用. toString()方法输出即可。
如:StringBuffer sf = new StringBuffer();
sf.append("abcdef");
System.out.println(sf.toString()); //==>abcdef
System.out.println(sf.reverse().toString()); //==>fedcba
2008年8月7日
from: http://www.blogjava.net/jorwen/archive/2008/08/07/220676.html
很久以前看某本书整理的,忘了哪本了,现在贡献出来。不断补充,总共大概20个左右,抓紧补充中,完成前大家稍等
1)在select语句中使用条件逻辑
1 select ename,sal,
2 case when sal <= 2000 then 'UNDERPAID'
3 when sal >= 4000 then 'OVERPAID'
4 else 'OK'
5 end as status
6 from emp
ENAME SAL STATUS
---------- ---------- ---------
SMITH 800 UNDERPAID
ALLEN 1600 UNDERPAID
WARD 1250 UNDERPAID
JONES 2975 OK
MARTIN 1250 UNDERPAID
BLAKE 2850 OK
CLARK 2450 OK
SCOTT 3000 OK
KING 5000 OVERPAID
TURNER 1500 UNDERPAID
ADAMS 1100 UNDERPAID
JAMES 950 UNDERPAID
FORD 3000 OK
MILLER 1300 UNDERPAID
2)从表中随机返回n条记录
1 select *
2 from (
3 select ename, job
4 from emp
5 order by dbms_random.value()
6 )
7 where rownum <= 5
3)按照子串排序
比如要从EMP表中返回员工名字和职位,并且按照职位字段最后2个字符排序
1 select ename,job
2 from emp
3 order by substr(job,length(job)-2)
ENAME JOB
---------- ---------
KING PRESIDENT
SMITH CLERK
ADAMS CLERK
JAMES CLERK
MILLER CLERK
JONES MANAGER
CLARK MANAGER
BLAKE MANAGER
ALLEN SALESMAN
MARTIN SALESMAN
WARD SALESMAN
TURNER SALESMAN
SCOTT ANALYST
FORD ANALYST
4)处理空值排序
当被排序的列存在空值,如果希望空值不影响现有排序
1 select ename,sal,comm
2 from emp
3 order by comm nulls last
ENAME SAL COMM
------ ----- ---------
TURNER 1500 0
ALLEN 1600 300
WARD 1250 500
MARTIN 1250 1400
SMITH 800
JONES 2975
JAMES 950
MILLER 1300
FORD 3000
ADAMS 1100
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000
1 select ename,sal,comm
2 from emp
3 order by comm desc nulls first
ENAME SAL COMM
------ ----- ----------
SMITH 800
JONES 2975
CLARK 2450
BLAKE 2850
SCOTT 3000
KING 5000
JAMES 950
MILLER 1300
FORD 3000
ADAMS 1100
MARTIN 1250 1400
WARD 1250 500
ALLEN 1600 300
TURNER 1500 0
5)根据数据项的键排序
比如如果job是“SALESMAN”,根据COMM排序,否则根据SAL排序
1 select ename,sal,job,comm
2 from emp
3 order by case when job = 'SALESMAN' then comm else sal end
ENAME SAL JOB COMM
---------- ---------- --------- ----------
TURNER 1500 SALESMAN 0
ALLEN 1600 SALESMAN 300
WARD 1250 SALESMAN 500
SMITH 800 CLERK
JAMES 950 CLERK
ADAMS 1100 CLERK
MARTIN 1250 SALESMAN 1300
MILLER 1300 CLERK
CLARK 2450 MANAGER
BLAKE 2850 MANAGER
JONES 2975 MANAGER
SCOTT 3000 ANALYST
FORD 3000 ANALYST
6)从一个表中查找另一个表中没有的值
比如要从DEPT中查找在表EMP中不存在数据的所有部门(数据中,DEPTNO值为40的记录在表EMP中不存在)
1 select deptno from dept
2 minus
3 select deptno from emp
7)在运算和比较时使用null值
null不会等于和不等于任何值,null和自己都不等于。以下例子是当comm有null的情况下列出比“WARD”提成低的员工。 (coalesce函数将null转换为其他值)
1 select ename,comm,coalesce(comm,0)
2 from emp
3 where coalesce(comm,0) < ( select comm
4 from emp
5 where ename = 'WARD' )
ENAME COMM COALESCE(COMM,0)
---------- ---------- ----------------
SMITH 0
ALLEN 300 300
JONES 0
BLAKE 0
CLARK 0
SCOTT 0
KING 0
TURNER 0 0
ADAMS 0
JAMES 0
FORD 0
MILLER 0
8)删除重复记录
对于名字重复的记录,保留一个
1 delete from dupes
2 where id not in ( select min(id)
3 from dupes
4 group by name )
9)合并记录
比如如下需求:
如果表EMP_COMMISSION中的某员工也存在于EMP表,那么更新comm为1000
如果以上员工已经更新到1000的员工,如果他们SAL少于2000,删除他们
否则,从表中提取该员工插入表EMP_COMMISSION
1 merge into emp_commission ec
2 using (select * from emp) emp
3 on (ec.empno=emp.empno)
4 when matched then
5 update set ec.comm = 1000
6 delete where (sal < 2000)
7 when not matched then
8 insert (ec.empno,ec.ename,ec.deptno,ec.comm)
9 values (emp.empno,emp.ename,emp.deptno,emp.comm)
10)用sql生成sql
1 select 'select count(*) from '||table_name||';' cnts
2 from user_tables;
(user_tables是oracle的元数据表之一)
CNTS
----------------------------------------
select count(*) from ANT;
select count(*) from BONUS;
select count(*) from DEMO1;
select count(*) from DEMO2;
select count(*) from DEPT;
select count(*) from DUMMY;
select count(*) from EMP;
select count(*) from EMP_SALES;
select count(*) from EMP_SCORE;
select count(*) from PROFESSOR;
select count(*) from T;
select count(*) from T1;
select count(*) from T2;
select count(*) from T3;
select count(*) from TEACH;
select count(*) from TEST;
select count(*) from TRX_LOG;
select count(*) from X;
11)计算字符在字符串里的出现次数
1 select (length('10,CLARK,MANAGER')-
2 length(replace('10,CLARK,MANAGER',',','')))/length(',')
3 as cnt
4 from t1
先计算原字符串长度,再减去去掉逗号的长度,这个差再除以‘,’的长度
12)将数字和字母分离
原数据是:
DATA
---------------
SMITH800
ALLEN1600
WARD1250
JONES2975
MARTIN1250
BLAKE2850
CLARK2450
SCOTT3000
KING5000
TURNER1500
ADAMS1100
JAMES950
FORD3000
MILLER1300
1 select replace(
2 translate(data,'0123456789','0000000000'),'0') ename,
3 to_number(
4 replace(
5 translate(lower(data),
6 'abcdefghijklmnopqrstuvwxyz',
7 rpad('z',26,'z')),'z')) sal
8 from (
9 select ename||sal data from emp
10 )
ENAME SAL
---------- ----------
SMITH 800
ALLEN 1600
WARD 1250
JONES 2975
MARTIN 1250
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000
TURNER 1500
ADAMS 1100
JAMES 950
FORD 3000
MILLER 1300
思路是很复杂的,比如先去除数字,是先把所有数字翻译为0,然后用replace去掉0.
13)根据表中的行创建分割列表
表中数据:
DEPTNO EMPS
------ ----------
10 CLARK
10 KING
10 MILLER
20 SMITH
20 ADAMS
20 FORD
20 SCOTT
20 JONES
30 ALLEN
30 BLAKE
30 MARTIN
30 JAMES
30 TURNER
30 WARD
1 select deptno,
2 ltrim(sys_connect_by_path(ename,','),',') emps
3 from (
4 select deptno,
5 ename,
6 row_number() over
7 (partition by deptno order by empno) rn,
8 count(*) over
9 (partition by deptno) cnt
10 from emp
11 )
12 where level = cnt
13 start with rn = 1
14 connect by prior deptno = deptno and prior rn = rn-1
查询结果
DEPTNO EMPS
------- ------------------------------------
10 CLARK,KING,MILLER
20 SMITH,JONES,SCOTT,ADAMS,FORD
30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
14)按字母顺序排序
1 select old_name, new_name
2 from (select old_name, replace(sys_connect_by_path(c, ' '), ' ') new_name
3 from (select e.ename old_name,
4 row_number() over(partition by e.ename order by substr(e.ename, iter.pos, 1)) rn,
5 substr(e.ename, iter.pos, 1) c
6 from emp e, (select rownum pos from emp) iter
7 where iter.pos <= length(e.ename)
8 order by 1) x
9 start with rn = 1
10 connect by prior rn = rn - 1
11 and prior old_name = old_name)
12 where length(old_name) = length(new_name)
You would like the result to be:
OLD_NAME NEW_NAME
---------- --------
ADAMS AADMS
ALLEN AELLN
BLAKE ABEKL
CLARK ACKLR
FORD DFOR
JAMES AEJMS
JONES EJNOS
KING GIKN
MARTIN AIMNRT
MILLER EILLMR
SCOTT COSTT
SMITH HIMST
TURNER ENRRTU
WARD ADRW
2008年8月6日
转自:http://www.phpchina.com/26200/viewspace_28436.html
2008-03-05 10:45:16 / 个人分类:js
1 判断select选项中 是否存在Value="paraValue"的Item
2 向select选项中 加入一个Item
3 从select选项中 删除一个Item
4 删除select中选中的项
5 修改select选项中 value="paraValue"的text为"paraText"
6 设置select中text="paraText"的第一个Item为选中
7 设置select中value="paraValue"的Item为选中
8 得到select的当前选中项的value
9 得到select的当前选中项的text
10 得到select的当前选中项的Index
11 清空select的项
js 代码
// 1.判断select选项中 是否存在Value="paraValue"的Item
function jsSelectIsExitItem(objSelect, objItemValue) {
var isExit = false;
for (var i = 0; i < objSelect.options.length; i++) {
if (objSelect.options[i].value == objItemValue) {
isExit = true;
break;
}
}
return isExit;
}
// 2.向select选项中 加入一个Item
function jsAddItemToSelect(objSelect, objItemText, objItemValue) {
//判断是否存在
if (jsSelectIsExitItem(objSelect, objItemValue)) {
alert("该Item的Value值已经存在");
} else {
var varItem = new Option(objItemText, objItemValue);
objSelect.options.add(varItem);
alert("成功加入");
}
}
// 3.从select选项中 删除一个Item
function jsRemoveItemFromSelect(objSelect, objItemValue) {
//判断是否存在
if (jsSelectIsExitItem(objSelect, objItemValue)) {
for (var i = 0; i < objSelect.options.length; i++) {
if (objSelect.options[i].value == objItemValue) {
objSelect.options.remove(i);
break;
}
}
alert("成功删除");
} else {
alert("该select中 不存在该项");
}
}
// 4.删除select中选中的项
function jsRemoveSelectedItemFromSelect(objSelect) {
var length = objSelect.options.length - 1;
for(var i = length; i >= 0; i--){
if(objSelect[i].selected == true){
objSelect.options[i] = null;
}
}
}
// 5.修改select选项中 value="paraValue"的text为"paraText"
function jsUpdateItemToSelect(objSelect, objItemText, objItemValue) {
//判断是否存在
if (jsSelectIsExitItem(objSelect, objItemValue)) {
for (var i = 0; i < objSelect.options.length; i++) {
if (objSelect.options[i].value == objItemValue) {
objSelect.options[i].text = objItemText;
break;
}
}
alert("成功修改");
} else {
alert("该select中 不存在该项");
}
}
// 6.设置select中text="paraText"的第一个Item为选中
function jsSelectItemByValue(objSelect, objItemText) {
//判断是否存在
var isExit = false;
for (var i = 0; i < objSelect.options.length; i++) {
if (objSelect.options[i].text == objItemText) {
objSelect.options[i].selected = true;
isExit = true;
break;
}
}
//Show出结果
if (isExit) {
alert("成功选中");
} else {
alert("该select中 不存在该项");
}
}
// 7.设置select中value="paraValue"的Item为选中
document.all.objSelect.value = objItemValue;
// 8.得到select的当前选中项的value
var currSelectValue = document.all.objSelect.value;
// 9.得到select的当前选中项的text
var currSelectText = document.all.objSelect.options[document.all.objSelect.selectedIndex].text;
// 10.得到select的当前选中项的Index
var currSelectIndex = document.all.objSelect.selectedIndex;
// 11.清空select的项
document.all.objSelect.options.length = 0;
2008年8月1日
一张表中:TEST
三个字段 ID,EVENTID,TIME
ID各个都不同..TIME 也不同..EVENTID有几条记录都一样
现在想查记录,如果eventid 有相同的记录,那只取time最新的那条记录
用如下的SQL即可获取所需的数据:
select * from TEST a where a.TIME =(select max(TIME) from TEST where EVENTID=a.EVENTID)
另:如果TEST表中还有一个字段,OTHEREVENTID,这个字段是EVENTID下的一个分类,即 相同的EVENTID 下有不同的
OTHEREVENTID ,类似如下数据:
ID, EVENTID, OTHEREVENTID, TIME
1001 1001001 100100101 2008-08-01 22:11:15
1002 1001001 100100101 2008-08-01 25:11:15
1003 1001001 100100102 2008-08-01 28:11:15
1004 1001001 100100102 2008-08-01 30:11:15
1005 1001002 100100201 2008-08-02 25:52:15
1006 1001003 100100301 2008-08-03 28:11:15
这样想查询最新那条记录的话,则需加上OTHEREVENTID做为条件,即:
select * from TEST a where a.TIME =(select max(TIME) from TEST where EVENTID=a.EVENTID and OTHEREVENTID='100100102')
即可.
|