sql server - আমি কিভাবে ডুপ্লিকেট সারি মুছে ফেলতে পারি?
sql-server tsql (20)
একটি মোটামুটি বড় SQL Server
টেবিল (অর্থাৎ 300,000+ সারি) থেকে সদৃশ সারি অপসারণ করার সেরা উপায় কি?
সারি, অবশ্যই, RowID
পরিচয় ক্ষেত্রের অস্তিত্বের কারণে নিখুঁত সদৃশ হবে না।
MyTable
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
অ্যাপ্লিকেশন স্তর থেকে (দুর্ভাগ্যবশত)। আমি সম্মত হচ্ছি যে ডুপ্লিকেশন প্রতিরোধের সঠিক উপায় একটি অনন্য সূচক ব্যবহারের মাধ্যমে ডাটাবেস স্তরের উপর, কিন্তু এসকিউএল সার্ভার 2005-এ, একটি সূচককে শুধুমাত্র 900 বাইটের অনুমতি দেওয়া হয় এবং আমার ভার্চার (২048) ক্ষেত্রটি এটিকে দূরে ফেলে দেয়।
আমি জানি না এটি কতটা কার্যকর হবে, তবে আমি মনে করি আপনি এটি প্রয়োগ করার জন্য একটি ট্রিগার লিখতে পারেন, এমনকি যদি আপনি সরাসরি সূচকের সাথে এটি করতে না পারেন। কিছুটা এইরকম:
-- given a table stories(story_id int not null primary key, story varchar(max) not null)
CREATE TRIGGER prevent_plagiarism
ON stories
after INSERT, UPDATE
AS
DECLARE @cnt AS INT
SELECT @cnt = Count(*)
FROM stories
INNER JOIN inserted
ON ( stories.story = inserted.story
AND stories.story_id != inserted.story_id )
IF @cnt > 0
BEGIN
RAISERROR('plagiarism detected',16,1)
ROLLBACK TRANSACTION
END
এছাড়াও, ভার্চার (২048) আমার কাছে ক্ষতিকারক শোনাচ্ছে (জীবনের কিছু জিনিস 2048 বাইট, তবে এটি বেশ অস্বাভাবিক); এটা কি সত্যিই ওয়ারচার না (সর্বোচ্চ)?
একই গঠন সঙ্গে নতুন খালি টেবিল তৈরি করুন
এই মত প্রশ্ন চালানো
INSERT INTO tc_category1 SELECT * FROM tc_category GROUP BY category_id, application_id HAVING count(*) > 1
তারপর এই প্রশ্নের চালান
INSERT INTO tc_category1 SELECT * FROM tc_category GROUP BY category_id, application_id HAVING count(*) = 1
আপনি যে সারিগুলি সরাতে চলেছেন তার পূর্বরূপ দেখতে চান এবং রাখা কোনও অনুলিপি সারিগুলিতে নিয়ন্ত্রণ রাখেন। http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/ দেখুন
with MYCTE as (
SELECT ROW_NUMBER() OVER (
PARTITION BY DuplicateKey1
,DuplicateKey2 -- optional
ORDER BY CreatedAt -- the first row among duplicates will be kept, other rows will be removed
) RN
FROM MyTable
)
DELETE FROM MYCTE
WHERE RN > 1
আমি SQL সার্ভার টেবিল থেকে সদৃশ সারি মুছে ফেলার জন্য CTE পছন্দ করব
দৃঢ়ভাবে এই নিবন্ধটি অনুসরণ করার সুপারিশ :: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/
মূল পালন করে
WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)
DELETE FROM CTE WHERE RN<>1
মূল রাখা ছাড়া
WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)
আমি এই পদ্ধতির সাথে সাথে সহায়ক হতে পারব এবং এটি সহায়ক হতে পারে এবং সমস্ত এসকিউএল সার্ভারগুলিতে কাজ করে: বেশিরভাগ ক্ষেত্রেই কেবলমাত্র একটি - দুটি সদৃশ, এবং আইডি এবং সদৃশগুলির গণনা জানা যায়। এক্ষেত্রে:
SET ROWCOUNT 1 -- or set to number of rows to be deleted
delete from myTable where RowId = DuplicatedID
SET ROWCOUNT 0
আমি একটি টেবিল ছিল যেখানে আমি নন-ডুপ্লিকেট সারি সংরক্ষণ করতে হবে। আমি গতি বা দক্ষতা নিশ্চিত নই।
DELETE FROM myTable WHERE RowID IN (
SELECT MIN(RowID) AS IDNo FROM myTable
GROUP BY Col1, Col2, Col3
HAVING COUNT(*) = 2 )
এই কাজ করার আরেকটি সম্ভাব্য উপায়
;
--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3
ORDER BY ( SELECT 0)) RN
FROM #MyTable)
DELETE FROM cte
WHERE RN > 1;
আমি ORDER BY (SELECT 0)
ব্যবহার করছি কারণ এটি অনির্ধারিত যা কোন টাই এর ইভেন্টে সংরক্ষণ করতে সারি।
RowID
অর্ডারে RowID
সংরক্ষণ করতে আপনি উদাহরণস্বরূপ ORDER BY RowID DESC
ব্যবহার করতে পারেন
এক্সিকিউশন পরিকল্পনা
এই জন্য মৃত্যুদন্ড পরিকল্পনাটি প্রায়ই স্বতঃসিদ্ধ এবং স্বীকৃত উত্তরগুলির চেয়ে বেশি কার্যকরী হয় কারণ এটি স্ব যোগদানের প্রয়োজন হয় না।
এই তবে, সবসময় না. এক জায়গা যেখানে GROUP BY
সমাধান পছন্দ করা যেতে পারে এমন পরিস্থিতি যেখানে একটি হ্যাশ সমষ্টি একটি স্ট্রিম সমষ্টিতে অগ্রাধিকারে চয়ন করা হবে।
ROW_NUMBER
সমাধানটি সর্বদা একই প্ল্যানটি প্রদান করবে যখন GROUP BY
কৌশল আরও বেশি নমনীয়।
হাশ সামগ্রিক পদ্ধতির পক্ষে হতে পারে এমন উপাদানগুলি হ'ল
- বিভাজন কলামে কোন দরকারী সূচক নেই
- অপেক্ষাকৃত কম গ্রুপ প্রতিটি গ্রুপে অপেক্ষাকৃত বেশি duplicates
এই দ্বিতীয় ক্ষেত্রে চরম সংস্করণগুলিতে (যদি প্রতিটিতে অনেকগুলি সদৃশ সহ খুব কম সংখ্যক গোষ্ঠী থাকে) তবে একটি নতুন টেবিলে রাখতে সারিগুলিকে কেবল সন্নিবেশ করাতে পারে এবং মূলত TRUNCATE
এবং মোছার তুলনায় লগিং কমিয়ে আনতে তাদের অনুলিপি করা যেতে পারে। সারির একটি খুব উচ্চ অনুপাত।
এই নকল রেকর্ড মুছে ফেলার সবচেয়ে সহজ উপায়
DELETE FROM tblemp WHERE id IN
(
SELECT MIN(id) FROM tblemp
GROUP BY title HAVING COUNT(id)>1
)
http://askme.indianyouth.info/details/how-to-dumplicate-record-from-table-in-using-sql-105
এখনো আরেকটি সহজ সমাধান http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server pasted লিঙ্ক পাওয়া http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server । এই সহজে বোঝার জন্য এবং একই ধরণের সমস্যার জন্য কার্যকর বলে মনে হচ্ছে। এটি যদিও এসকিউএল সার্ভারের জন্য কিন্তু ব্যবহৃত ধারণাটি গ্রহণযোগ্য নয়।
লিঙ্কযুক্ত পাতা থেকে প্রাসঙ্গিক অংশ এখানে রয়েছে:
এই তথ্য বিবেচনা করুন:
EMPLOYEE_ID ATTENDANCE_DATE
A001 2011-01-01
A001 2011-01-01
A002 2011-01-01
A002 2011-01-01
A002 2011-01-01
A003 2011-01-01
তাহলে আমরা কিভাবে সেই নকল তথ্য মুছে ফেলতে পারি?
প্রথম, নিম্নলিখিত কোড ব্যবহার করে যে টেবিলের একটি পরিচয় কলাম সন্নিবেশ করান:
ALTER TABLE dbo.ATTENDANCE ADD AUTOID INT IDENTITY(1,1)
এটি সমাধানের জন্য নিচের কোডটি ব্যবহার করুন:
DELETE FROM dbo.ATTENDANCE WHERE AUTOID NOT IN (SELECT MIN(AUTOID) _
FROM dbo.ATTENDANCE GROUP BY EMPLOYEE_ID,ATTENDANCE_DATE)
এখানে সদৃশ অপসারণ একটি ভাল নিবন্ধ।
এটি কেন কঠিন তা নিয়ে আলোচনা করে: " এসকিউএল সম্পর্কযুক্ত বীজগণিতের উপর ভিত্তি করে, এবং সদৃশ সম্পর্কযুক্ত বীজগণিতের মধ্যে ঘটতে পারে না, কারণ একটি সেটে সদৃশ অনুমতি নেই। "
টেম্প টেবিল সমাধান, এবং দুটি MySQL উদাহরণ।
ভবিষ্যতে আপনি এটি একটি ডাটাবেস স্তর, অথবা একটি অ্যাপ্লিকেশন দৃষ্টিকোণ থেকে প্রতিরোধ করতে যাচ্ছেন। আমি ডেটাবেস স্তরের পরামর্শ দেব কারণ আপনার ডাটাবেসটি রেফারেন্সিয়াল অখণ্ডতা বজায় রাখার জন্য দায়ী হওয়া উচিত, ডেভেলপাররা কেবল সমস্যাগুলি সৃষ্টি করবে;)
এটি প্রথম সারির ব্যতীত সদৃশ সারি মুছবে
DELETE
FROM
Mytable
WHERE
RowID NOT IN (
SELECT
MIN(RowID)
FROM
Mytable
GROUP BY
Col1,
Col2,
Col3
)
পড়ুন ( http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server অপসারণ- ডুপ্লিকেট - রাউন্ড-থেকে- A- টেবিল- ইন- SQL- http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server )
ওহ নিশ্চিত। একটি টেম্প টেবিল ব্যবহার করুন। যদি আপনি একটি একক, অসাধারণ অভিনয়কারী বিবৃতি চান যা "কাজ করে" তবে আপনি যেতে পারেন:
DELETE FROM MyTable WHERE NOT RowID IN
(SELECT
(SELECT TOP 1 RowID FROM MyTable mt2
WHERE mt2.Col1 = mt.Col1
AND mt2.Col2 = mt.Col2
AND mt2.Col3 = mt.Col3)
FROM MyTable mt)
মূলত, টেবিলে প্রতিটি সারির জন্য, উপ-নির্বাচনটি সারির শীর্ষ সারিটি সারির সারির মতই থাকে যা ঠিক সারির মত। সুতরাং আপনি ROWID গুলির তালিকাটি শেষ করেন যা "আসল" নন-ডুপ্লিকেটযুক্ত সারির প্রতিনিধিত্ব করে।
নিম্নলিখিত ক্যোয়ারী সদৃশ সারি মুছতে দরকারী। এই উদাহরণের টেবিলে একটি পরিচয় কলাম এবং ID
রয়েছে যার মধ্যে ডুপ্লিকেট ডেটা রয়েছে কলাম 1, কলাম 2 এবং কলাম Column3
।
DELETE FROM TableName
WHERE ID NOT IN (SELECT MAX(ID)
FROM TableName
GROUP BY Column1,
Column2,
Column3
/*Even if ID is not null-able SQL Server treats MAX(ID) as potentially
nullable. Because of semantics of NOT IN (NULL) including the clause
below can simplify the plan*/
HAVING MAX(ID) IS NOT NULL)
নিম্নোক্ত স্ক্রিপ্ট GROUP BY
, HAVING
, ORDER BY
ব্যবহার করে এক প্রশ্নের মধ্যে দেখায় এবং ফলাফলগুলিকে সদৃশ কলাম এবং এর গণনার সাথে দেখায়।
SELECT YourColumnName,
COUNT(*) TotalCount
FROM YourTableName
GROUP BY YourColumnName
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC
নীচের প্রশ্নের ব্যবহার করে আমরা একক কলাম বা একাধিক কলামের উপর ভিত্তি করে নকল রেকর্ড মুছে ফেলতে সক্ষম হতে পারি। নীচের কোয়েরি দুটি কলামের উপর ভিত্তি করে মুছে ফেলা হয়। টেবিল নামটি হল: testing
এবং কলামের নাম empno,empname
DELETE FROM testing WHERE empno not IN (SELECT empno FROM (SELECT empno, ROW_NUMBER() OVER (PARTITION BY empno ORDER BY empno)
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)
or empname not in
(select empname from (select empname,row_number() over(PARTITION BY empno ORDER BY empno)
AS [ItemNumber] FROM testing) a WHERE ItemNumber > 1)
সঠিক ডুপ্লিকেটযুক্ত সারিগুলি (ছোট টেবিলগুলির জন্য) মুছতে দ্রুত এবং মলিন করুন:
select distinct * into t2 from t1;
delete from t1;
insert into t1 select * from t2;
drop table t2;
সিটিই ব্যবহার করে। ধারণাটি এমন একটি বা একাধিক কলামে যোগদান করা যা একটি সদৃশ রেকর্ড তৈরি করে এবং আপনি যা চান তা সরাতে পারেন:
;with cte as (
select
min(PrimaryKey) as PrimaryKey
UniqueColumn1,
UniqueColumn2
from dbo.DuplicatesTable
group by
UniqueColumn1, UniqueColumn1
having count(*) > 1
)
delete d
from dbo.DuplicatesTable d
inner join cte on
d.PrimaryKey > cte.PrimaryKey and
d.UniqueColumn1 = cte.UniqueColumn1 and
d.UniqueColumn2 = cte.UniqueColumn2;
CREATE TABLE car(Id int identity(1,1), PersonId int, CarId int)
INSERT INTO car(PersonId,CarId)
VALUES(1,2),(1,3),(1,2),(2,4)
--SELECT * FROM car
;WITH CTE as(
SELECT ROW_NUMBER() over (PARTITION BY personid,carid order by personid,carid) as rn,Id,PersonID,CarId from car)
DELETE FROM car where Id in(SELECT Id FROM CTE WHERE rn>1)
DELETE
FROM
table_name T1
WHERE
rowid > (
SELECT
min(rowid)
FROM
table_name T2
WHERE
T1.column_name = T2.column_name
);
DELETE LU
FROM (SELECT *,
Row_number()
OVER (
partition BY col1, col1, col3
ORDER BY rowid DESC) [Row]
FROM mytable) LU
WHERE [row] > 1
SELECT DISTINCT *
INTO tempdb.dbo.tmpTable
FROM myTable
TRUNCATE TABLE myTable
INSERT INTO myTable SELECT * FROM tempdb.dbo.tmpTable
DROP TABLE tempdb.dbo.tmpTable