2012-06-19 36 views
13

Bạn có một bảng table1 chứa id cột, đó là int(11), not null, auto_increment và bắt đầu từ 1.truy vấn sql để xóa hồ sơ

Giả sử, bạn có 10.000 hồ sơ. Rõ ràng là id của hồ sơ cuối cùng là 10.000. Khi bạn đã xóa 3 bản ghi, bạn có 9,997 bản ghi trong bảng, nhưng giá trị id bản ghi cuối cùng vẫn là 10.000 (nếu bản ghi cuối cùng không bị xóa).

Cách hiển thị bản ghi nào đã bị xóa bằng truy vấn 1 sql?

Cảm ơn bạn.

+2

Tạo bảng có 10.000 giá trị tuần tự để hoạt động như một bảng tra cứu. Sau đó chọn tất cả các bản ghi từ tra cứu của bạn không tồn tại trong bảng mục tiêu của bạn. * (Điều này sẽ luôn nhanh hơn việc cố gắng tạo các ID bị thiếu.) * – MatBailie

+0

Nếu DMBS của bạn có hàm generate_series() (tôi không nghĩ mysql có nó), bạn có thể sử dụng nó, dựa trên {min, max }, thay vì một bảng * *. – wildplasser

+0

+1 bởi vì tôi đã học được điều gì đó mới bằng cách trả lời câu hỏi :) Một câu hỏi phong nha :) –

Trả lời

5

Tôi nghĩ dễ nhất là có bảng giả/tạm thời chỉ với id. 1-1000 rồi rời khỏi bàn đó.

Nhưng hãy chắc chắn xóa các bản ghi "đã xóa" khỏi bảng giả/tạm thời của bạn khi bạn đã hoàn tất. Nếu không, chúng sẽ hiển thị mọi lúc.

>> EDIT < < Bạn có thể làm tự tham gia để tìm ra nếu bạn id thiếu ....

select a.id + 1 MissingIds 
from <table> a 
left join <table> b 
    on a.id = b.id - 1 
where b.id is null 
    and a.id < 10000 
+3

Thật dễ dàng, chắc chắn, nhưng không phải là rất chuyên nghiệp imo :) –

+0

tất cả những gì bạn thực sự cần là một bảng số hoặc cách để tạo số trên bay – dotjoe

+3

@ AndriusNaruševičius Không đồng ý. Đôi khi nó chuyên nghiệp để có một phương pháp chứng minh thất bại, không phải là một quá phức tạp. – fancyPants

1
DECLARE @myTestTable1 TABLE 
(
id INT IDENTITY(1,1) NOT NULL 
,testVal int 
) 

DECLARE @increment AS int = 1 

WHILE (@increment <= 10000) 
BEGIN 
INSERT INTO @myTestTable1 
VALUES (@increment) 

SET @increment += 1 
END 

DELETE FROM @myTestTable1 WHERE id IN (100,200,300) 

--SELECT * FROM @myTestTable1 

;WITH Missing (missnum, maxid) 
AS 
(
    SELECT 1 AS missnum, (select max(id) from @myTestTable1) 
    UNION ALL 
    SELECT missnum + 1, maxid FROM Missing 
    WHERE missnum < maxid 
    ) 
    SELECT missnum 
    FROM Missing 
    LEFT OUTER JOIN @myTestTable1 tt on tt.id = Missing.missnum 
    WHERE tt.id is NULL 
    OPTION (MAXRECURSION 0); 

Nhưng mất nhiều thời gian. Chúng ta phải giảm thời gian.

2

Tôi đã sử dụng this answer làm tài liệu tham khảo.

Bạn có thể sử dụng truy vấn sau đây để tìm khoảng trống, bản chất sẽ cung cấp cho bạn hồ sơ đã xóa "dải ô". Ví dụ: trong ví dụ dưới đây, bạn nhận được 2 hàng trở lại trong kết quả cuối cùng và các giá trị là 2 và 3 và 6 và 7. Vì vậy, bạn biết rằng các hàng có ID từ 2 đến 3 đã bị xóa và các hàng có ID từ 6 đến 7 đã bị xóa (cho tổng số 4 hàng đã xóa).

Tôi tin rằng điều này đáp ứng yêu cầu của bạn về việc nhận được kết quả cuối cùng trong "1 truy vấn SQL" và hơn nữa, không sử dụng bảng trung gian hoặc giả nào.

delimiter $$ 
use test 
$$ 

create table mytable (id int not null auto_increment, name varchar(100), primary key (id)); 
$$ 

insert into mytable (name) values('a')$$ 
insert into mytable (name) values('b')$$ 
insert into mytable (name) values('c')$$ 
insert into mytable (name) values('d')$$ 
insert into mytable (name) values('e')$$ 
insert into mytable (name) values('f')$$ 
insert into mytable (name) values('g')$$ 
insert into mytable (name) values('h')$$ 


delete from mytable where id = 2$$ 
delete from mytable where id = 3$$ 
delete from mytable where id = 6$$ 
delete from mytable where id = 7$$ 


SELECT (t1.id + 1) as gap_starts_at 
    , (SELECT MIN(t3.id) -1 
      FROM mytable t3 
     WHERE t3.id > t1.id) as gap_ends_at 
    FROM mytable t1 
WHERE NOT EXISTS (SELECT t2.id FROM mytable t2 WHERE t2.id = t1.id + 1) 
HAVING gap_ends_at IS NOT NULL 

Output:

gap_starts_at gap_ends_at 
2    3 
6    7 
1

Vì vậy, để bắt đầu, tôi sẽ chỉ cho cách dễ nhất để tạo ra 10.000 hồ sơ. Không có truy vấn lớn-ass, không có biến. Thời gian thực hiện: ~ 3ms. LINK

Bây giờ về kích hoạt mà tôi đã hứa. LINK

Như bạn có thể thấy, thật dễ dàng để tạo một tài khoản. Hãy nhớ rằng trình kích hoạt tốt hơn không chỉ vì không cần tham gia nhiều lần, nhưng bạn cũng có thể lưu trữ ngày, id người dùng, v.v. (ví dụ rất có thể mở rộng). Và điểm kích hoạt chính trên các kết nối là: bạn không quan tâm có bao nhiêu bản ghi có/sẽ/sẽ là. Bạn không cần phải nghiêm khắc về kích thước. Đó là lý do tại sao tôi gọi câu trả lời là sam yi không đủ chuyên nghiệp. Xin lỗi vì sự hiểu lầm, tôi khá chắc chắn không ai trong số chúng tôi muốn xúc phạm bất cứ ai.

Bằng cách tạo ví dụ này, tôi đã học được một vài điều. Hy vọng rằng bạn cũng đã làm vậy :)

+0

http://sqlfiddle.com/#!2/ab17a/1 - Tôi đã xây dựng một giao diện người dùng thay thế cho lệnh "delimiter" (lưu ý "|") bên dưới bảng lược đồ. Sử dụng điều này, bạn có thể xây dựng tùy chọn dựa trên trình kích hoạt của mình. –

+0

Aah, tôi hiểu, cảm ơn vì điều này. Tuy nhiên, một điều tôi học: P –

+0

Sẽ sử dụng liên kết của bạn nếu bạn không nhớ :) –

Các vấn đề liên quan