如果只有三个字段如下, Delete table1 from id like (Select Max(table1.Id) from table1 inner join table1 table1 table2 on table1.a=table2.a and table1.b=table2.b and table1.id<>table2.id)
如果: 1 aa bb 2 cc dd 3 ee ff 4 cc dd 5 cc dd CrazyFor(蚂蚁) 删少了! DELETE T FROM T,T T1 WHERE T.a=T1.a and T.b=T1.b and T.id > T1.ida,b 都相同时,保留 id 最小的!
DELETE T FROM T T1 WHERE T.a=T1.a and T.b=T1.b and T.id > T1.id
《一道褒贬不一的 SQL 考试题》 http://www.triaton.com.cn/cgi-bin/lb5k/topic.cgi?forum=4&topic=97&show=0第一题:1.如果 T 表还有一字段 F 数据类型为自动增量整型(唯一,不会重复), 而且 T 表中含有除 F 字段外,请删除其它字段完全相同的重复多余的脏记录数据: 本问题就是一个清理"逻辑重复"记录的问题,当然,这种情况完全可以利用主键约束来 杜绝!然而,现实情况经常是原始数据在"洗涤"后,方可安全使用,而且逻辑主键过早的 约束,将会给采集原始数据带来不便,例如:从刷卡机上读取考勤记录。到了应用数据 的时候,脏数据就该被扫地出门了! 之所以题中要保留一个自动标识列,是因为它的确 是下面答案所必须的前提: DELETE L FROM "成绩表" L JOIN "成绩表" R ON L."学生ID" = R."学生ID" AND L."课程ID" = R."课程ID" AND L.F > R.F 这是思路最精巧且最直接有效的方法之一。用不等自联接,正好可以将同一组重复数 据中 F 字段值最小的那一条留下,并选出其它的删掉,如果只有一条,自然也不会被选 中了。这里还要强调一下,大家一定要分清楚被操作的基本表也就是 DELETE 关键字 后的表和过滤条件所使用的由基本表连接而成的二维表数据集,也就是 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 ) 这种方法思路很简单,就像翻译自然语言,很精确地描述了符合条件记录的特性,甚至 第二个条件的确多余。至少应该用一个 >= 号合并这两个条件或只保留任意一个条件, 提高效率。 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 ON L."学生ID" = R."学生ID" AND L."课程ID" = R."课程ID" AND L.F>R.F 这样,极大地减小了在线数据被无意破坏的可能性,当然数据提前备份也很重要。同理 UPDATE 和 INSERT 写操作也应照此行事。从数据库原理的关系运算的角度来看 INSERT、 UPDATE 和 DELETE 这些写操作都属于典型的"选择(Selection)"运算,UPDATE 和 INSERT 而且还是"投影(Projection)"运算,它们都是这些关系运算的"写"应用的表现形式。 其实,查询的目的也本来无非就是浏览、删除、更 新或插入。通常写操作也比读操作消耗更大,如果索引过多,只会降低效率。 选择"子查询"还是"连接"在效率是有差别的,但最关键的差别还是表现在查询的结果 集的读写性上,开发人员在写一个"只读"应用的查询记录集时,"子查询"和"连接"各自 的效率就是应该首先考虑的问题,但是如果要实现"可写"应用的查询结果集,则无论是 相关还是非相关子查询都是在复杂应用中难以避免的。 以上解决方案中,应该说第一种方法,简洁有效,很有创意,是值得推荐的方法。当然, 最简单的写法应该是: DELETE T FROM T,T T1 WHERE T.学生ID=T1.学生ID and T.课程ID=T1.课程ID and T.F < T1.F 其实这就是方法一的"标准"(但确实实不是《ANSI/ISO SQL》标准)连接写法,以下各 题答案为了便于读者理解,一般不采用这种写法,这也是《ANSI/ISO SQL》标准所鼓 励的,JOIN 确实更容易地表达表之间的关系,有兴趣的读者可自行改写。如果使用 "*="实现两表以上的外连接时,要注意此时 WHERE 子句的 AND 条件是有顺序的,尽 管《ANSI/ISO SQL》标准不允许 WHERE 条件的顺序影响查询结果,但是 FROM 子句 的各表连接的顺序可以影响查询结果。
delect from 表 where id not in (select min(id) from 表 group by a,b)
我解决了,应该这样写DELETE FROM tbl_testgeng WHERE (id IN (SELECT MAX(id) FROM tbl_testgeng GROUP BY bhos, chos having count(chos) = 2))谢谢你们了.
如果: 1 aa bb 2 cc dd 3 ee ff 4 cc dd 5 cc ddcc dd 的有两条以上?DELETE T FROM T T1 WHERE T.a=T1.a and T.b=T1.b and T.id > T1.iddelect from 表 where id not in (select min(id) from 表 group by a,b)都是对的!
Delete table1 from id like (Select Max(table1.Id) from table1 inner join table1 table1 table2 on table1.a=table2.a and table1.b=table2.b and table1.id<>table2.id)
1 aa bb
2 cc dd
3 ee ff
4 cc dd
5 cc dd CrazyFor(蚂蚁) 删少了!
DELETE T
FROM T,T T1
WHERE T.a=T1.a and T.b=T1.b and T.id > T1.ida,b 都相同时,保留 id 最小的!
FROM T T1
WHERE T.a=T1.a and T.b=T1.b and T.id > T1.id
http://www.triaton.com.cn/cgi-bin/lb5k/topic.cgi?forum=4&topic=97&show=0第一题:1.如果 T 表还有一字段 F 数据类型为自动增量整型(唯一,不会重复),
而且 T 表中含有除 F 字段外,请删除其它字段完全相同的重复多余的脏记录数据: 本问题就是一个清理"逻辑重复"记录的问题,当然,这种情况完全可以利用主键约束来
杜绝!然而,现实情况经常是原始数据在"洗涤"后,方可安全使用,而且逻辑主键过早的
约束,将会给采集原始数据带来不便,例如:从刷卡机上读取考勤记录。到了应用数据
的时候,脏数据就该被扫地出门了! 之所以题中要保留一个自动标识列,是因为它的确
是下面答案所必须的前提: DELETE L
FROM "成绩表" L
JOIN "成绩表" R
ON L."学生ID" = R."学生ID" AND L."课程ID" = R."课程ID" AND L.F > R.F 这是思路最精巧且最直接有效的方法之一。用不等自联接,正好可以将同一组重复数
据中 F 字段值最小的那一条留下,并选出其它的删掉,如果只有一条,自然也不会被选
中了。这里还要强调一下,大家一定要分清楚被操作的基本表也就是 DELETE 关键字
后的表和过滤条件所使用的由基本表连接而成的二维表数据集,也就是 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
) 这种方法思路很简单,就像翻译自然语言,很精确地描述了符合条件记录的特性,甚至
第二个条件的确多余。至少应该用一个 >= 号合并这两个条件或只保留任意一个条件,
提高效率。 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
ON L."学生ID" = R."学生ID" AND L."课程ID" = R."课程ID" AND L.F>R.F 这样,极大地减小了在线数据被无意破坏的可能性,当然数据提前备份也很重要。同理
UPDATE 和 INSERT 写操作也应照此行事。从数据库原理的关系运算的角度来看 INSERT、
UPDATE 和 DELETE 这些写操作都属于典型的"选择(Selection)"运算,UPDATE 和 INSERT
而且还是"投影(Projection)"运算,它们都是这些关系运算的"写"应用的表现形式。
其实,查询的目的也本来无非就是浏览、删除、更
新或插入。通常写操作也比读操作消耗更大,如果索引过多,只会降低效率。 选择"子查询"还是"连接"在效率是有差别的,但最关键的差别还是表现在查询的结果
集的读写性上,开发人员在写一个"只读"应用的查询记录集时,"子查询"和"连接"各自
的效率就是应该首先考虑的问题,但是如果要实现"可写"应用的查询结果集,则无论是
相关还是非相关子查询都是在复杂应用中难以避免的。 以上解决方案中,应该说第一种方法,简洁有效,很有创意,是值得推荐的方法。当然,
最简单的写法应该是: DELETE T
FROM T,T T1
WHERE T.学生ID=T1.学生ID and T.课程ID=T1.课程ID and T.F < T1.F 其实这就是方法一的"标准"(但确实实不是《ANSI/ISO SQL》标准)连接写法,以下各
题答案为了便于读者理解,一般不采用这种写法,这也是《ANSI/ISO SQL》标准所鼓
励的,JOIN 确实更容易地表达表之间的关系,有兴趣的读者可自行改写。如果使用
"*="实现两表以上的外连接时,要注意此时 WHERE 子句的 AND 条件是有顺序的,尽
管《ANSI/ISO SQL》标准不允许 WHERE 条件的顺序影响查询结果,但是 FROM 子句
的各表连接的顺序可以影响查询结果。
WHERE (id IN
(SELECT MAX(id)
FROM tbl_testgeng
GROUP BY bhos, chos having count(chos) = 2))谢谢你们了.
1 aa bb
2 cc dd
3 ee ff
4 cc dd
5 cc ddcc dd 的有两条以上?DELETE T
FROM T T1
WHERE T.a=T1.a and T.b=T1.b and T.id > T1.iddelect from 表 where id not in (select min(id) from 表 group by a,b)都是对的!