আমি কীভাবে সদৃশ সারিগুলি সরিয়ে ফেলতে পারি?


1284

মোটামুটি বড় 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

13
পোস্টগ্র্রেএসকিউএল ব্যবহারকারীদের জন্য এটির দ্রুত টিপস (প্রচুর পরিমাণে এটির সাথে সংযুক্ত করা হয়): পিজি সিটিই শর্তাদি আপডেটযোগ্য মতামত হিসাবে প্রকাশ করে না যাতে আপনি DELETE FROMসরাসরি কোনও সিটিই পদ ব্যবহার করতে পারবেন না । স্ট্যাকওভারফ্লো.com
ক্রেগ

@CraigRinger একই জন্য সত্য সাইবেস - আমি অবশিষ্ট সমাধান এখানে সংগৃহীত হয়েছে (খুব পিজি এবং অন্যদের জন্য বৈধ হওয়া উচিত: stackoverflow.com/q/19544489/1855801 (ঠিক প্রতিস্থাপন ROWID()যদি থাকে, RowID কলাম দ্বারা ফাংশন)
মাফ-নরম

12
এখানে কেবল একটি সতর্কতা যুক্ত করতে। কোনও ডি-সদৃশ প্রক্রিয়া চলাকালীন, সর্বদা আপনি প্রথমে কী মুছছেন তা ডাবল পরীক্ষা করুন! এটি সেই অঞ্চলগুলির মধ্যে একটি যেখানে দুর্ঘটনাক্রমে ভাল ডেটা মুছে ফেলা খুব সাধারণ।
জেফ ডেভিস 1

উত্তর:


1141

কোন NULLs ধরে নেওয়া যাক, আপনি GROUP BYঅনন্য কলাম, এবং সারি হিসাবে RowId রাখা। তারপরে, কেবল সারি আইডি না থাকা সমস্ত কিছু মুছুন:SELECTMIN (or MAX)

DELETE FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

যদি কোনও পূর্ণসংখ্যার পরিবর্তে আপনার একটি জিইউডি থাকে তবে আপনি প্রতিস্থাপন করতে পারেন

MIN(RowId)

সঙ্গে

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))

327
এটি কি কাজ করবে? DELETE FROM MyTable WHERE RowId NOT IN (SELECT MIN(RowId) FROM MyTable GROUP BY Col1, Col2, Col3);
জর্জি স্কলি

10
@Andriy - এসকিউএল সার্ভার LEFT JOINকম দক্ষ চেয়ে NOT EXISTS sqlinthewild.co.za/index.php/2010/03/23/... একই সাইট এছাড়াও তুলনা NOT INবনাম NOT EXISTSsqlintjeeild.co.za/index.php/2010/02/18/not-exists-vs-not-in 3-এর মধ্যে আমি মনে করি NOT EXISTSসেরা অভিনয় করে। তিনটিই স্ব-যোগদানের সাথে একটি পরিকল্পনা তৈরি করবে যদিও তা এড়ানো যায়।
মার্টিন স্মিথ

12
@ মার্টিন, @ জর্জি: সুতরাং, আমি একটি ছোট পরীক্ষা করেছি। এখানে বর্ণিত হিসাবে একটি বড় টেবিল তৈরি করা হয়েছে এবং জনবহুল হয়েছে: sqlinthewild.co.za/index.php/2010/03/23/… তারপরে দুটি নির্বাচন করা হয়েছিল, একটি বাম জোনে + যেখানে নূরের কৌশল ব্যবহার করে, অন্যটি ব্যবহার করে না একটি. তারপরে আমি ফাঁসির পরিকল্পনা নিয়ে এগিয়ে গেলাম, এবং অনুমান করি কী? ক্যোয়ারী খরচ বাম জন্য 18% না, একটি জন্য 82% বিরুদ্ধে JOIN ছিল বড় আমার কাছে বিস্ময়। আমি এমন কিছু করেছি যা আমার উচিত ছিল না বা এর বিপরীতে হওয়া উচিত, যা সত্য যদি সত্য হয় তবে আমি তা জানতে চাই।
অ্যান্ড্রি এম

16
@ জর্জিস্কলি একটি দুর্দান্ত উত্তর দিয়েছেন। আমি এটিকে এমন টেবিলে ব্যবহার করেছি যেখানে আমার পিএইচপি বাগের সদৃশ সারি তৈরি হয়েছিল।
ফিলিপ কেয়ার্নস

12
দুঃখিত তবে DELETE MyTable FROM MyTableসঠিক বাক্য গঠন কেন ? আমি এখানেDELETE ডকুমেন্টেশনে একটি বিকল্প হিসাবে টেবিলের নামটি সঠিকভাবে স্থাপন করতে দেখছি না । এটি অন্যের কাছে সুস্পষ্ট হলে দুঃখিত; আমি এসকিউএল-র একজন নবাগত মাত্র শিখার চেষ্টা করছি। কেন এটি কাজ করে তার চেয়েও গুরুত্বপূর্ণ: সেখানে টেবিলের নাম অন্তর্ভুক্ত করা বা না করার মধ্যে পার্থক্য কী?
লেভিনিনজা

760

এটি করার আরেকটি সম্ভাব্য উপায়

; 

--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উদাহরণস্বরূপ আপনি ব্যবহার করতে পারেন যাতে সর্বশেষতম সংরক্ষণ করতেORDER BY RowID DESC

কার্যকর করার পরিকল্পনা

এর জন্য কার্যকর করার পরিকল্পনাটি স্বীকৃত উত্তরের চেয়ে প্রায়শই সহজ এবং আরও কার্যকর কারণ এটি স্ব-যোগদানের প্রয়োজন হয় না।

কার্যকর করার পরিকল্পনা

তবে, সবসময় না. GROUP BYসমাধানটিকে অগ্রাধিকার দেওয়া হতে পারে এমন এক জায়গাটি হ'ল স্ট্রিম সামগ্রীর পক্ষে অগ্রাধিকার হিসাবে হ্যাশ সমষ্টি নির্বাচন করা হবে।

ROW_NUMBERসমাধান সবসময় কাছাকাছি একই পরিকল্পনা দেব যেহেতু GROUP BYকৌশল নমনীয় হয়।

কার্যকর করার পরিকল্পনা

হ্যাশ সামগ্রিক পদ্ধতির পক্ষে হতে পারে এমন কারণগুলি হবে

  • পার্টিশনের কলামগুলিতে কোনও দরকারী সূচক নেই
  • প্রতিটি গ্রুপে তুলনামূলকভাবে আরও বেশি সদৃশ সহ অপেক্ষাকৃত কম গ্রুপ

এই দ্বিতীয় মামলার চূড়ান্ত সংস্করণগুলিতে (যদি প্রত্যেকটিতে অনেকগুলি TRUNCATEনকলের সাথে খুব কয়েকটি গোষ্ঠী থাকে) একটি নতুন সারণীতে সারি সন্নিবেশ করানো বিবেচনা করতে পারে তারপরে মূল-টিপুন এবং সেগুলি মুছার তুলনায় লগিংকে হ্রাস করতে পুনরায় অনুলিপি করতে পারে সারিগুলির খুব বেশি অনুপাত।


28
যদি আমি যোগ করতে পারি: গৃহীত উত্তরটি ব্যবহার করে এমন টেবিলগুলির সাথে কাজ করে না uniqueidentifier। এটি একটি খুব সহজ এবং যে কোনও টেবিলে নিখুঁতভাবে কাজ করে। ধন্যবাদ মার্টিন
ব্রুনোএলএম

15
এটি এমন দুর্দান্ত উত্তর! ডুপ্লিকেটগুলি বুঝতে পারার আগে আমি পুরানো পিকে সরিয়ে ফেললে এটি ইভেন্টে কাজ করেছিল। +100
মিকেল এলিয়াসন

12
আমি ডিবিএ.এসইতে এই প্রশ্নের জিজ্ঞাসা করার এবং তার পরে (এই উত্তর দিয়ে) উত্তর দেওয়ার পরামর্শ দিচ্ছি। তারপরে আমরা এটিকে আমাদের প্রচলিত উত্তরগুলির তালিকায় যুক্ত করতে পারি ।
নিক চামাস

16
গৃহীত উত্তরের বিপরীতে, এটি এমন একটি টেবিলের উপরেও কাজ করেছিল যার তুলনায় কোনও কী ( RowId) নেই ।
vossad01

8
এটি অন্যদিকে সমস্ত এসকিউএল সার্ভার সংস্করণে কাজ করে না
ডেভিড

150

মাইক্রোসফ্ট সমর্থন সাইটে নকল অপসারণ সম্পর্কে একটি ভাল নিবন্ধ আছে । এটি বেশ রক্ষণশীল - তাদের পৃথক পদক্ষেপে আপনারা সমস্ত কিছু করেছেন - তবে এটি বড় টেবিলগুলির বিরুদ্ধে ভালভাবে কাজ করা উচিত।

আমি অতীতে এটি করতে স্ব-যোগদানের ব্যবহার করেছি, যদিও এটি সম্ভবত একটি প্রত্যাবর্তন ধারা দ্বারা প্রেজেন্টেড হতে পারে:

DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField 
AND dupes.secondDupField = fullTable.secondDupField 
AND dupes.uniqueField > fullTable.uniqueField

পারফেক্ট! আমার পুরানো মারিয়্যাডবি সংস্করণ 10.1.xx. এর নকল সারিগুলি সরিয়ে ফেলার এটি সবচেয়ে কার্যকর উপায় i ধন্যবাদ!
মাতাল এম এম

বোঝা অনেক সহজ এবং সহজ!
মার্ক

98

নিম্নলিখিত কোয়েরি সদৃশ সারি মুছে ফেলার জন্য দরকারী। এই উদাহরণে টেবিল রয়েছে IDএকটি পরিচয় কলাম হিসাবে এবং কলাম যা তথ্যে প্রতিলিপি আছে Column1, Column2এবং 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 

1
মাইএসকিউএল ত্রুটি প্রথম স্ক্রিপ্টের সাথে 'আপনি লক্ষ্য টেবিল নির্দিষ্ট করতে পারবেন না' টেবিলের নাম 'আপডেট থেকে
ফর্ম

ইতিমধ্যে রিপোর্ট করা ত্রুটি ছাড়াও ডি রোসাদো, আপনার প্রথম ক্যোয়ারীটিও খুব ধীর। সংশ্লিষ্ট SELECT ক্যোয়ারী আমার সেটআপটি গ্রহণ করেছে + - গৃহীত উত্তরের চেয়ে 20 গুণ বেশি লম্বা।
পারভাস

8
@ পারভাস - প্রশ্নটি এসকিউএল সার্ভারকে মাইএসকিউএল নয়। বাক্য গঠনটি এসকিউএল সার্ভারে ঠিক আছে। এছাড়াও মাইএসকিউএল সাব কোয়েরিগুলি অনুকূলকরণের জন্য কুখ্যাতভাবে উদাহরণস্বরূপ দেখুন । এই উত্তরটি এসকিউএল সার্ভারে ঠিক আছে। আসলে NOT INপ্রায়শই এর চেয়ে ভাল পারফর্ম করে OUTER JOIN ... NULL। আমি HAVING MAX(ID) IS NOT NULLক্যোয়ারীতে একটি যুক্ত করব যদিও অর্থহীনভাবে এটি প্রয়োজনীয় হওয়া উচিত নয় কারণ এটি এখানে
মার্টিন স্মিথ

2
PostgreSQL 8.4 এ দুর্দান্ত কাজ করে।
উত্তর

63
delete t1
from table t1, table t2
where t1.columnA = t2.columnA
and t1.rowid>t2.rowid

Postgres:

delete
from table t1
using table t2
where t1.columnA = t2.columnA
and t1.rowid > t2.rowid

একটি এসকিউএল সার্ভার প্রশ্নে পোস্টগ্রিস সমাধান পোস্ট করুন কেন?
লঙ্ক্যমার্ট

2
@ ল্যানকিমার্ট কারণ পোস্টগ্রিজ ব্যবহারকারীরাও এখানে আসছেন। এই উত্তরের স্কোর দেখুন।
গ্যাব্রিয়েল

2
আমি এখানে , এখানে এবং এখানে কিছু জনপ্রিয় এসকিউএল প্রশ্নগুলিতে দেখেছি । ওপি তার উত্তর পেয়েছে এবং বাকি সবাইও কিছুটা সহায়তা পেয়েছে। সমস্যা নেই আইএমএইচও।
গ্যাব্রিয়েল

44
DELETE LU 
FROM   (SELECT *, 
               Row_number() 
                 OVER ( 
                   partition BY col1, col1, col3 
                   ORDER BY rowid DESC) [Row] 
        FROM   mytable) LU 
WHERE  [row] > 1 

1
আমি এই বার্তাটি অ্যাজুর এসকিউএল ডিডাব্লুতে পেয়েছি: একটি নিষ্ক্রিয় বিবৃতিতে বর্তমানে একটি ফ্রম ক্লজ সমর্থিত নয়।
অমিত

40

এটি প্রথম সারি বাদে সদৃশ সারিগুলি মুছে ফেলবে

DELETE
FROM
    Mytable
WHERE
    RowID NOT IN (
        SELECT
            MIN(RowID)
        FROM
            Mytable
        GROUP BY
            Col1,
            Col2,
            Col3
    )

( Http://www.codeproject.com/Articles/157977/ সরান- ডুপ্লিকেট- Rows-from-a- টেবিল- ইন- এসকিউএল- সার্ভার ) দেখুন


10
মাইএসকিএল-এর জন্য এটি ত্রুটি দেবে: ত্রুটি কোড: 1093. আপনি এফআরওএম ক্লজটিতে আপডেটের জন্য লক্ষ্য টেবিল 'মাইটেবিল' নির্দিষ্ট করতে পারবেন না। তবে এই ছোট্ট পরিবর্তনটি mysql এর জন্য কাজ করবে: Mytable থেকে যেখানে সারি নেই সরিয়ে দিন (কল 1, কল 2, কল 3 দ্বারা মাইটেবল গ্রুপ থেকে আইডি থেকে নির্বাচন করুন আইডি থেকে নির্বাচন করুন)
রীতেশ

35

আমি স্কিল সার্ভার টেবিল থেকে নকল সারি মুছে ফেলার জন্য সিটিই পছন্দ করব prefer

দৃঢ়ভাবে এই নিবন্ধটি :: অনুসরণ করতে সুপারিশ 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)

24

সদৃশ সারিগুলি আনতে:

SELECT
name, email, COUNT(*)
FROM 
users
GROUP BY
name, email
HAVING COUNT(*) > 1

সদৃশ সারিগুলি মুছতে:

DELETE users 
WHERE rowid NOT IN 
(SELECT MIN(rowid)
FROM users
GROUP BY name, email);      

মাইএসকিউএল ব্যবহারকারীদের জন্য নোট করুন যে প্রথমে এটি হওয়া দরকার DELETE FROM, দ্বিতীয়, এটি কাজ করবে না, কারণ আপনি যে SELECTটেবিলটি থেকে এসেছেন সেখান থেকে আপনি পারবেন না DELETE। মাইএসকিউএলে এই বিস্ফোরণগুলি বন্ধ হয়ে যায় MySQL error 1093
orhor Mé

23

সঠিক ডুপ্লিকেটযুক্ত সারিগুলি মুছতে দ্রুত এবং ময়লা (ছোট টেবিলগুলির জন্য):

select  distinct * into t2 from t1;
delete from t1;
insert into t1 select *  from t2;
drop table t2;

3
নোট করুন যে প্রশ্নটি আসলে অ-নির্ভুল নকল (ডুয়েটো সারি আইডি) নির্দিষ্ট করে।
ডেনিস জাহেরউদ্দিন

21

আমি অভ্যন্তরীণ যোগদানের 1 টি সমাধান গণনা (*)> থাকা 1 টি পছন্দ করি কারণ পড়তে আমার আরও সহজ মনে হয়েছে এবং এটি চালানোর আগে কী মুছে ফেলা হবে তা যাচাই করার জন্য একটি নির্বাচন বিবৃতিতে পরিণত হওয়া খুব সহজ ছিল।

--DELETE FROM table1 
--WHERE id IN ( 
     SELECT MIN(id) FROM table1 
     GROUP BY col1, col2, col3 
     -- could add a WHERE clause here to further filter
     HAVING count(*) > 1
--)

এটি কি অভ্যন্তরীণ কোয়েরিতে প্রদর্শিত সমস্ত রেকর্ড মুছে দেয় না। আমাদের কেবল ডুপ্লিকেট অপসারণ এবং মূল সংরক্ষণ করতে হবে।
স্যান্ডি

3
আপনি কেবল নির্বাচিত ধারাটিতে ন্যূনতম (আইডি) ভিত্তিতে সর্বনিম্ন আইডি দিয়ে একজনকে ফিরিয়ে দিচ্ছেন।
জেমস এরিকো

2
প্রশ্নের প্রথম, দ্বিতীয় এবং শেষ রেখাগুলি কমেন্ট করুন।
জেমস এরিকো

7
এটি সমস্ত সদৃশগুলি পরিষ্কার করবে না। যদি আপনার কাছে 3 টি সারি থাকে যা সদৃশ হয় তবে এটি কেবল এমআইএন (আইডি) দিয়ে সারিটি নির্বাচন করবে এবং সেইটিকে মুছবে, নকলের মতো দুটি সারি রেখে যাবে।
ক্লো

2
তবুও, আমি বার বার বার বার এই বিবৃতিটি ব্যবহার করে শেষ করেছি, যাতে এটি সংযোগের সময় শেষ না করে কম্পিউটারের ঘুমের পরিবর্তে আসলে অগ্রগতি করে। MAX(id)পরবর্তী নকলগুলি মুছে ফেলার জন্য আমি এটিকে পরিবর্তন করেছি এবং LIMIT 1000000অভ্যন্তরীণ কোয়েরিতে যুক্ত করেছি যাতে এটি পুরো টেবিলটি স্ক্যান করতে না পারে। এটি অন্যান্য উত্তরের চেয়ে অনেক দ্রুত অগ্রগতি দেখিয়েছিল, যা কয়েক ঘন্টা ধরে স্থির থাকে বলে মনে হয়। টেবিলটি পরিচালনাযোগ্য আকারে ছাঁটাই করার পরে, আপনি অন্যান্য প্রশ্নের সাথে শেষ করতে পারেন। টিপ: নিশ্চিত করুন যে কল 1 / কল 2 / কল 3 এর দ্বারা গ্রুপ অনুসারে সূচক রয়েছে।
ক্লো

17
SELECT  DISTINCT *
      INTO tempdb.dbo.tmpTable
FROM myTable

TRUNCATE TABLE myTable
INSERT INTO myTable SELECT * FROM tempdb.dbo.tmpTable
DROP TABLE tempdb.dbo.tmpTable

5
আপনার যদি আমার টেবিলের জন্য বিদেশী কী রেফারেন্স থাকে তবে ছাঁটাই কাজ করবে না।
সমীর আলিভাই

15

আমি ভেবেছিলাম যে আমি আমার সমাধানটি ভাগ করব কারণ এটি বিশেষ পরিস্থিতিতে কাজ করে। আমি আমার ক্ষেত্রে সদৃশ মান সহ টেবিলের একটি বিদেশী কী নেই (কারণ মানগুলি অন্য ডিবি থেকে নকল করা হয়েছিল)।

begin transaction
-- create temp table with identical structure as source table
Select * Into #temp From tableName Where 1 = 2

-- insert distinct values into temp
insert into #temp 
select distinct * 
from  tableName

-- delete from source
delete from tableName 

-- insert into source from temp
insert into tableName 
select * 
from #temp

rollback transaction
-- if this works, change rollback to commit and execute again to keep you changes!!

পিএস: এই জাতীয় জিনিসগুলিতে কাজ করার সময় আমি সর্বদা লেনদেন ব্যবহার করি, এটি কেবল পুরোপুরি কার্যকর করা নিশ্চিত করে না, তবে আমাকে কোনও ঝুঁকি ছাড়াই পরীক্ষার অনুমতি দেয়। তবে অবশ্যই নিশ্চিত হওয়ার জন্য আপনার যেভাবেই হোক ব্যাকআপ নেওয়া উচিত ...


14

এই ক্যোয়ারীটি আমার পক্ষে খুব ভাল পারফরম্যান্স দেখিয়েছে:

DELETE tbl
FROM
    MyTable tbl
WHERE
    EXISTS (
        SELECT
            *
        FROM
            MyTable tbl2
        WHERE
            tbl2.SameValue = tbl.SameValue
        AND tbl.IdUniqueValue < tbl2.IdUniqueValue
    )

এটি 2 এমের টেবিল থেকে 30 সেকেন্ডের তুলনায় 1 এম সারি মুছে ফেলেছে (50% নকল)


14

সিটিই ব্যবহার করছি। ধারণাটি হ'ল এক বা একাধিক কলামে যোগদান করা যা সদৃশ রেকর্ড গঠন করে এবং তারপরে যাকে পছন্দ করে তা সরিয়ে ফেলুন:

;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;

1
আমি মনে করি আপনি আপনার যোগদান করে একটি এ্যান্ডএড মিস করছেন।
জাস্টিন আর।

13

তবুও অন্য সহজ সমাধানটি এখানে আটকানো লিঙ্কটিতে পাওয়া যাবে । এটি উপলব্ধি করা সহজ এবং অনুরূপ সমস্যার বেশিরভাগ ক্ষেত্রে কার্যকর বলে মনে হয়। এটি এসকিউএল সার্ভারের জন্য হলেও এটি ব্যবহৃত ধারণাটি গ্রহণযোগ্যতার চেয়ে বেশি।

এখানে লিঙ্কযুক্ত পৃষ্ঠা থেকে প্রাসঙ্গিক অংশ রয়েছে:

এই ডেটা বিবেচনা করুন:

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) 

1
"উপলব্ধি করা সহজ", "কার্যকর বলে মনে হচ্ছে", তবে পদ্ধতিটি কী কী অন্তর্ভুক্ত রয়েছে সে সম্পর্কে একটি শব্দও নয় Just কেবলমাত্র কল্পনা করুন যে লিঙ্কটি অবৈধ হয়ে গেছে, তখন কীভাবে এই পদ্ধতিটি উপলব্ধি করা সহজ এবং কার্যকর ছিল তা জানতে কী ব্যবহার হবে ? আপনার পোস্টে পদ্ধতির বর্ণনার প্রয়োজনীয় অংশগুলি বিবেচনা করুন, অন্যথায় এটি কোনও উত্তর নয়।
অ্যান্ড্রি এম

এই পদ্ধতিটি টেবিলগুলির জন্য দরকারী যেখানে আপনার এখনও পরিচয় সংজ্ঞায়িত হয়নি। প্রাথমিক কীটি সংজ্ঞায়িত করার জন্য আপনাকে প্রায়শই নকলগুলি থেকে মুক্তি দিতে হবে!
জেফ ডেভিস

@ জেফডাভিস - ROW_NUMBERআপনি আরম্ভ করার আগে একটি নতুন কলাম যুক্ত করার দৈর্ঘ্যে যাওয়ার প্রয়োজন ছাড়াই সংস্করণটি সেই ক্ষেত্রে ভাল কাজ করে।
মার্টিন স্মিথ

12

সদৃশ অপসারণ সম্পর্কে আরও একটি ভাল নিবন্ধ এখানে ।

এটি কেন কঠোর তা নিয়ে আলোচনা করে: " এসকিউএল রিলেশনাল বীজগণিতের উপর ভিত্তি করে, এবং ডুপ্লিকেটগুলি রিলেশনাল বীজগণিতের মধ্যে ঘটতে পারে না, কারণ ডুপ্লিকেটগুলিকে একটি সেটে অনুমতি দেওয়া হয় না। "

টেম্প টেবিল সমাধান, এবং দুটি mysql উদাহরণ।

ভবিষ্যতে আপনি এটি একটি ডাটাবেস স্তরে বা একটি অ্যাপ্লিকেশন দৃষ্টিকোণ থেকে প্রতিরোধ করতে যাচ্ছেন। আমি ডাটাবেস স্তরটি সুপারিশ করব কারণ আপনার ডাটাবেসটি রেফারেন্সিয়াল অখণ্ডতা বজায় রাখার জন্য দায়বদ্ধ হওয়া উচিত, বিকাশকারীরা কেবল সমস্যা সৃষ্টি করবেন;)


1
এসকিউএল মাল্টি সেট উপর ভিত্তি করে। তবে এটি সেটগুলির উপর ভিত্তি করে থাকলেও এই দুটি টিপলস (1, এ) এবং (2, এ) আলাদা।
অ্যান্ড্রু

12

ওহ নিশ্চিত একটি টেম্প টেবিল ব্যবহার করুন। আপনি যদি একটি একক, খুব-না-পারফরম্যান্ট স্টেটমেন্ট চান যা "কাজ করে" আপনি এর সাথে যেতে পারেন:

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 সন্ধান করে যা হুবহু বিবেচনাধীন সারির মতো। সুতরাং আপনি রাউআইডিগুলির একটি তালিকা তৈরি করবেন যা "আসল" নন-সদৃশ সারিগুলি উপস্থাপন করে।


11

আমার একটি টেবিল ছিল যেখানে আমার নন-সদৃশ সারিগুলি সংরক্ষণ করার প্রয়োজন ছিল। আমি গতি বা দক্ষতার বিষয়ে নিশ্চিত নই।

DELETE FROM myTable WHERE RowID IN (
  SELECT MIN(RowID) AS IDNo FROM myTable
  GROUP BY Col1, Col2, Col3
  HAVING COUNT(*) = 2 )

7
এটি ধরে নিয়েছে যে সর্বাধিক 1 টি সদৃশ রয়েছে।
মার্টিন স্মিথ

না কেন HAVING COUNT(*) > 1?
ফিলিপ এম

11

এটা ব্যবহার কর

WITH tblTemp as
(
SELECT ROW_NUMBER() Over(PARTITION BY Name,Department ORDER BY Name)
   As RowNumber,* FROM <table_name>
)
DELETE FROM tblTemp where RowNumber >1

10

অন্য উপায়টি হ'ল একই ক্ষেত্র এবং অনন্য সূচক সহ একটি নতুন টেবিল তৈরি করুন । তারপরে সমস্ত তথ্য পুরানো টেবিল থেকে নতুন টেবিলের দিকে সরান । স্বয়ংক্রিয়ভাবে এসকিউএল সার্ভার উপেক্ষা করুন (সদৃশ মান উপস্থিত থাকলে কী করা উচিত সে সম্পর্কেও একটি বিকল্প রয়েছে: উপেক্ষা করুন, বাধা দিন বা স্টেথ) সদৃশ মানগুলি। সুতরাং ডুপ্লিকেট সারি ছাড়াই আমাদের একই টেবিল রয়েছে। আপনি যদি অনন্য সূচক না চান তবে স্থানান্তর ডেটার পরে আপনি এটিকে ফেলে দিতে পারেন

বিশেষত বৃহত্তর টেবিলগুলির জন্য আপনি আপনার নতুন অনন্য সূচকযুক্ত টেবিলটিতে দ্রুত সমস্ত ডেটা স্থানান্তর করতে ডিটিএস (ডেটা আমদানি / রফতানি করতে এসএসআইএস প্যাকেজ) ব্যবহার করতে পারেন। Million মিলিয়ন সারির জন্য এটি কয়েক মিনিট সময় নেয়।


9

কোয়েরির নীচে ব্যবহার করে আমরা একক কলাম বা একাধিক কলামের ভিত্তিতে সদৃশ রেকর্ডগুলি মুছতে সক্ষম করতে পারি। কোয়েরির নীচে দুটি কলামের ভিত্তিতে মুছে ফেলা হচ্ছে। সারণীর নাম: 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)

9
  1. একই কাঠামো সহ নতুন ফাঁকা টেবিল তৈরি করুন

  2. এই জাতীয় জিজ্ঞাসা চালানো

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) > 1
  3. তারপরে এই কোয়েরিটি কার্যকর করুন

    INSERT INTO tc_category1
    SELECT *
    FROM tc_category
    GROUP BY category_id, application_id
    HAVING count(*) = 1

9

এটি সদৃশ রেকর্ড মোছার সহজতম উপায়

 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


কেন কেউ এই upvoting হয়? আপনার যদি একই আইডি দুটিরও বেশি থাকে তবে এটি কাজ করবে না। পরিবর্তে লিখুন: ট্রাবল্যাম্প থেকে মুছে ফেলুন যেখানে আইডিতে নেই (শিরোনাম অনুসারে ট্রাবল্যাম্প গ্রুপ থেকে মিনিট (আইডি) নির্বাচন করুন)
ক্রেল্লি

7

আমি এই পদ্ধতির উল্লেখ করবো পাশাপাশি এটি সহায়ক হতে পারে এবং সমস্ত এসকিউএল সার্ভারে কাজ করে: বেশিরভাগ ক্ষেত্রে কেবল একটিই থাকে - দুটি সদৃশ এবং আইডি এবং নকলের গণনা জানা যায়। এক্ষেত্রে:

SET ROWCOUNT 1 -- or set to number of rows to be deleted
delete from myTable where RowId = DuplicatedID
SET ROWCOUNT 0

7

আবেদনের স্তর থেকে (দুর্ভাগ্যক্রমে) আমি সম্মত হয়েছি যে অনুলিপি প্রতিরোধের সঠিক উপায়টি অনন্য সূচক ব্যবহারের মাধ্যমে ডাটাবেস পর্যায়ে রয়েছে তবে এসকিউএল সার্ভার ২০০৫-এ একটি সূচকটি কেবলমাত্র 900 বাইট হতে পারে এবং আমার বারচার (2048) ক্ষেত্রটি এড়িয়ে যায়।

এটি কতটা ভালভাবে সম্পাদন করবে তা আমি জানি না, তবে আমি মনে করি আপনি এটি প্রয়োগের জন্য একটি ট্রিগার লিখতে পারেন, এমনকি যদি আপনি সরাসরি কোনও সূচক দিয়ে নাও করতে পারেন। কিছুটা এইরকম:

-- 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 

এছাড়াও, বর্ণচর (2048) আমার কাছে ফিশ করে মনে হচ্ছে (জীবনের কিছু জিনিস 2048 বাইট, তবে এটি বেশ অস্বাভাবিক) mon এটি কি সত্যিই বারচর (সর্বোচ্চ) হওয়া উচিত নয়?



7
DELETE
FROM
    table_name T1
WHERE
    rowid > (
        SELECT
            min(rowid)
        FROM
            table_name T2
        WHERE
            T1.column_name = T2.column_name
    );

হাই কিশোরী, আপনি মুছার মন্তব্যের পরে অ্যালিসের নাম টি 1 টেবিলটি মিস করেছেন অন্যথায় এটি সিনট্যাক্স ব্যতিক্রমকে ছুঁড়ে ফেলবে।
নাগরাজ এম

6
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)

6

আপনি যে সারিগুলি সরাতে চলেছেন সেগুলির প্রাকদর্শন করতে চান এবং কোনটি সদৃশ সারি রাখবেন তা নিয়ন্ত্রণ করতে পারেন। Http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-d નકલ- ডেটা/ দেখুন

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.