星期五去一家公司面試sql資料庫工程師,有乙份筆試題目,其中有一題是:現在有乙個表t(姓名,手機號,****),手機號字段存在重覆記錄,要求用一句sql刪除重覆記錄。
我想了想寫了一句建立唯一索引的語句:
create unique index t_index on t(手機號)
交卷了,後來想想也不對,這樣只能保證以後不能新增重複的記錄,這樣寫會導致:當新增了重覆記錄時,發生錯誤,導致整個新增操作被回滾。實際上應該寫成這樣:
create unique index t_index on t(手機號) with ignore_dup_key
這樣才能保證當新增重覆記錄時候,忽略重覆記錄,如果有2條記錄是重複的,那麼只會新增其中的一條,而且不會在執行的時候發生錯誤。
面試人員看了我做的題,說讓我把這一題再重新做做,然後再給他看,我就重新想了2種寫法。我按照第一種寫法寫得語句,面試人員說這種辦法一看就是錯誤的。
第二種寫法,面試人員看說:基本是對的,就是效率差點。呵呵,他說的很對,效率確實差,
下面把兩種辦法都寫出來,測試環境sql server 2005:
首先建表:
create table t (ename varchar(10),mobile char(5),relation varchar(5))
insert into t values('abcd','12345','cc') --和第3個重複
insert into t values('ab', '12358','dd') --和第5個重複
insert into t values('abc', '12345','gg')
insert into t values('abde','24685','hh')
insert into t values('abdf', '12358','ag')
insert into t values('a', '54321','op')
select * into tt from t --以下的操作都在tt上進行
1.先說第二種寫法,就是通過子查詢,查到count大於1的記錄,不過這個語句經過測試,是錯誤的。
delete tt from tt t1
where
(select count(mobile) from tt t2 where t2.mobile = t1.mobile)>1
結果:(4 行受影響)
一下子刪除了4條記錄,也就是只剩下第4和第6條記錄,為什麼會這樣呢?主要是子查詢沒有變化,雖然tt一開始會刪除一條重複的記錄,但是子查詢的表沒變化,所以導致凡是tt表中count(mobile)>1的,也就是有重複的記錄,整個都刪除了。
2.第二種寫法,雖然語法有點問題,但是回家後,經過測試,應該說基本的想法是對的,就是查了一下資料,把語法改了一下。下面的語句適合mobile欄位重複的情況,如果還有其它欄位也重複,稍加修改就行。
delete t from t t1 inner join
(select *,row_number() over(partition by mobile order by mobile) as row from t
) t2
on t1.ename = t2.ename and t1.mobile = t2.mobile and t1.relation = t2.relation
where t2.row >1
從效率上看,對資料緩衝的讀取次數比較多,特別是worktble的讀取次數特別高,畢竟表中只有6條記錄。
呵呵,面試人員後來問我,為什麼我做的幾道題裡都用row_number,我沒回答,其實是最近正好看到這個函式,確實改進了sql server 2000中顯示行號的效率,挺有用的。
另一種更為簡單的刪除重覆記錄的寫法:
[sql]view plain
copy
print?
drop
table rt
create
table rt(a varchar(10),b varchar(10))
insert
into rt
select
'a1', 'b1'
union
allselect
'a1', 'b1'
union
allselect
'a1', 'b2'
;with t
as(
select *,
row_number() over(partition by a,b order
by a) rownum
from rt
) delete
from t
where rownum = 2
select *
from rt
/*
a b
a1 b1
a1 b2
*/
/*
;with t
as(
select *,
row_number() over(partition by a,b order
by a) rownum
from rt
) --很有意思的時候,這種寫法會把所有的3條資料都刪除掉,所以這種寫法是有問題的
delete
from t
from t t2
inner
join t t1
on t1.a = t2.a
and t1.b = t2.b
and t1.rownum = t2.rownum
and t1.rownum = 2
*/
drop table rt
create table rt(a varchar(10),b varchar(10))
insert into rt
select 'a1', 'b1' union all
select 'a1', 'b1' union all
select 'a1', 'b2'
;with tas(
select *,
row_number() over(partition by a,b order by a) rownum
from rt
)delete from t
where rownum = 2
select *
from rt
/*a b
a1 b1
a1 b2
*//*
;with tas(
select *,
row_number() over(partition by a,b order by a) rownum
from rt
)--很有意思的時候,這種寫法會把所有的3條資料都刪除掉,所以這種寫法是有問題的
delete from t
from t t2
inner join t t1
on t1.a = t2.a
and t1.b = t2.b
and t1.rownum = t2.rownum
and t1.rownum = 2
*/
SQL查詢重覆記錄,刪除重覆記錄
1 查詢表中多餘的重覆記錄,重覆記錄是根據單個字段 docid 來判斷 select from tablename where docid in select docid from tablename group by docid h ing count docid 1 例二 select from...
SQL 刪除重覆記錄
例如 id name value 1 a pp 2 a pp 3 b iii 4 b pp 5 b pp 6 c pp 7 c pp 8 c iii id是主鍵 要求得到這樣的結果 id name value 1 a pp 3 b iii 4 b pp 6 c pp 8 c iii 方法1delet...
刪除重覆記錄
我們經常在資料庫中有重複的記錄這時候我們希望刪除那些重複的記錄 你不要告訴我你是一條條手動刪除的哈 select distinct into newtable form 程式設計客棧nbsp tablename drop table tabwww.cppcns.comlename select in...