মাইএসকিউএল টেবিলের নকলগুলি কীভাবে মুছবেন?


158

আমাকে DELETEএকটি MySQLটেবিলের মধ্যে নির্দিষ্ট এসিডের জন্য সারিগুলি নকল করতে হবে ।

আমি কীভাবে এসকিউএল কোয়েরি দিয়ে এটি করতে পারি?

DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"

এরকম কিছু, তবে আমি কীভাবে এটি করব তা জানি না।


আপনার কি কেবল একবার এটি করা দরকার বা সারাক্ষণ এটি করার দরকার আছে?
বিলি ওনিল

সদৃশ রেকর্ডযুক্ত রেকর্ডগুলির মধ্যে কি একই ডেটা থাকে বা বাকী ক্ষেত্রগুলি একে অপরের থেকে আলাদা? আপনার যদি প্রথম বিকল্প থাকে আপনি কেবল সমস্ত রেকর্ড মুছতে পারেন তবে একটি, যদি আপনার দ্বিতীয় বিকল্প থাকে তবে আপনি কোন রেকর্ডটি রাখতে চান তা আপনি কীভাবে নির্ধারণ করছেন?
রেল_কিড

@Lex প্রথম বিকল্প। @ বিলি আমার সবসময় এটি করা দরকার।
আলী ডেমিরসি


1
মাইএসকিউএল এর বিভিন্ন সংস্করণে এখানে অনেকগুলি জিনিস পরিবর্তিত হয়েছে। এখানে যে কোনও সমাধানের পথে ঝাঁপ দেওয়ার আগে সাবধানতার সাথে আপনার মাইএসকিউএল সংস্করণটি পরীক্ষা করুন।
delatbabel

উত্তর:


215

এটি কোনও নতুন টেবিল তৈরি না করে জায়গায় নকলকে সরিয়ে দেয়

ALTER IGNORE TABLE `table_name` ADD UNIQUE (title, SID)

দ্রষ্টব্য: সূচক মেমরির মধ্যে ফিট করে তবেই ভাল কাজ করে


26
বিজ্ঞপ্তি: এটি সবচেয়ে পুরানো সদৃশ রেকর্ড রাখবে এবং নতুনগুলি মুছবে। আপনি যদি নতুন রাখতে চান তবে আপনি এটি দিয়ে এটি করতে পারবেন না ALTER IGNORE
হারালান ডবরেভ

9
InnoDB এর সাথে কাজ করছে বলে মনে হচ্ছে না। আমি ALTER TABLE foo ENGINE MyISAMএটিকে ঘিরে কাজ করার জন্য ছুটে এসেছি , ইঞ্জিনটি পরে পরিবর্তন করেছি।
মার্টিন

13
এটি মাইএসকিউএল> 5.5 এ ব্যর্থ হতে পারে, যদি তাই হয় তবে "সেট সেশন ওল্ড_াল্টার_ টেবিল = 1;" এবং "সেশনটি ওল্ড_াল্টার_সামগ্রী সেট করুন = 0;" বিবৃতি দেওয়ার আগে এবং পরে
চিলেটিম


2
@delatbabel এটি হ্রাস করার কারণ আপনি যে পৃষ্ঠাটিতে লিঙ্ক করেছেন তাতে দেওয়া হয়েছে is
বার্মার

133

মনে করুন employeeনীচের কলামগুলির সাথে আপনার একটি টেবিল রয়েছে:

employee (first_name, last_name, start_date)

সদৃশ first_nameকলাম দিয়ে সারিগুলি মুছতে :

delete
from employee using employee,
    employee e1
where employee.id > e1.id
    and employee.first_name = e1.first_name  

1
বাকী রেকর্ডটিতে এর সদৃশ গ্রুপে সর্বাধিক বা ন্যূনতম আইডি থাকবে?
হিমায়িত শিখা

বাকী রেকর্ডটিতে ন্যূনতম আইডি থাকবে কারণ এটি মুছে ফেলার শর্তটি পূরণ করে না এমন একমাত্র
পাবলো গেরেরো

1
employeeএকটি সূচী ম্যাচের জন্য নিজের বিরুদ্ধে যোগ দেওয়ার মতো মনে হচ্ছে এবং >একটি সূচীতে একটি চেক বড় টেবিলের জন্য ধীর হতে চলেছে। এটা ভাল হবে না SELECT MAX(ID) FROM t GROUP BY uniqueএবং তারপর JOINএর একটি সঠিক ম্যাচে IDকরতে MAX(ID)?
ebyrob

1
দুর্দান্ত উত্তর! আমার সময় বাঁচিয়েছে!
নেছার

56

কেবলমাত্র একক নয়, সমস্ত এসআইডি-এর জন্য অপসারণের নকলগুলি অনুসরণ করে।

টেম্প টেবিল সহ

CREATE TABLE table_temp AS
SELECT * FROM table GROUP BY title, SID;

DROP TABLE table;
RENAME TABLE table_temp TO table;

থেকে temp_table নতুনভাবে তৈরি হয়েছে এটির কোনও সূচক নেই। সদৃশ অপসারণ করার পরে আপনার সেগুলি পুনরায় তৈরি করতে হবে। আপনি টেবিলে কী সূচি রেখেছেন তা পরীক্ষা করতে পারেনSHOW INDEXES IN table

টেম্প টেবিল ছাড়া:

DELETE FROM `table` WHERE id IN (
  SELECT all_duplicates.id FROM (
    SELECT id FROM `table` WHERE (`title`, `SID`) IN (
      SELECT `title`, `SID` FROM `table` GROUP BY `title`, `SID` having count(*) > 1
    )
  ) AS all_duplicates 
  LEFT JOIN (
    SELECT id FROM `table` GROUP BY `title`, `SID` having count(*) > 1
  ) AS grouped_duplicates 
  ON all_duplicates.id = grouped_duplicates.id 
  WHERE grouped_duplicates.id IS NULL
)

4
GROUP-ing আপনার দ্বারা ভাগ করা ক্ষেত্রগুলির মানগুলির প্রতিটি সংমিশ্রণের জন্য কেবল একটি ফলাফল সারি তৈরি করে। সুতরাং সদৃশগুলি সরানো হবে।
কামিল জাজট

4
আমি প্রথম উপায় পছন্দ করি, এখানে খুব মার্জিত! : বি
এজলেস উপস্থিতি

1
@fiacre বিদেশি চাবি চেক সাময়িকভাবে নিষ্ক্রিয় করতে পারেন: stackoverflow.com/questions/15501673/... এছাড়াও আপনি ঝুঁকি যেতে পারে সারি অন্যান্য টেবিল পড়ুন কয়েকজনকে সরানোর, কিন্তু আপনি ক্যোয়ারী পরিবর্তনকারী দ্বারা নিয়ন্ত্রণ করতে পারেন যে রেকর্ড deduped টেবিলে বাছাই করা হয় SELECT * FROM table GROUP BY title, SID;এগুলি নির্ভর করে আপনি কী করছেন তা আপনি কতটা ভাল জানেন।
কামিল জাজোট

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

1
"টেম্প টেবিল ছাড়াই" পদ্ধতিটি সলিউশন সলিউশনের নিকটতম তবে মাইএসকিউএল ৫.7.৫-এ পরিবর্তিত কেবল হ্যান্ডলিং থেকে সাবধান থাকুন: dev.mysql.com/doc/refman/5.7/en/group-by-handling.html আমি এটি পেয়েছি "SELECT ANY_VALUE (id)
as

53

মাইএসকিউএল-এ স্থানটিতে সদৃশ সারিগুলি মোছা, (ধরে নিলাম আপনার কাছে সাজানোর জন্য টাইমস্ট্যাম্প কোল রয়েছে) ওয়াকথ্রু:

টেবিলটি তৈরি করুন এবং কয়েকটি সারি সন্নিবেশ করুন:

create table penguins(foo int, bar varchar(15), baz datetime);
insert into penguins values(1, 'skipper', now());
insert into penguins values(1, 'skipper', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(4, 'rico', now());
select * from penguins;
    +------+----------+---------------------+
    | foo  | bar      | baz                 |
    +------+----------+---------------------+
    |    1 | skipper  | 2014-08-25 14:21:54 |
    |    1 | skipper  | 2014-08-25 14:21:59 |
    |    3 | kowalski | 2014-08-25 14:22:09 |
    |    3 | kowalski | 2014-08-25 14:22:13 |
    |    3 | kowalski | 2014-08-25 14:22:15 |
    |    4 | rico     | 2014-08-25 14:22:22 |
    +------+----------+---------------------+
6 rows in set (0.00 sec)

সদৃশ জায়গায় সরিয়ে ফেলুন:

delete a
    from penguins a
    left join(
    select max(baz) maxtimestamp, foo, bar
    from penguins
    group by foo, bar) b
    on a.baz = maxtimestamp and
    a.foo = b.foo and
    a.bar = b.bar
    where b.maxtimestamp IS NULL;
Query OK, 3 rows affected (0.01 sec)
select * from penguins;
+------+----------+---------------------+
| foo  | bar      | baz                 |
+------+----------+---------------------+
|    1 | skipper  | 2014-08-25 14:21:59 |
|    3 | kowalski | 2014-08-25 14:22:15 |
|    4 | rico     | 2014-08-25 14:22:22 |
+------+----------+---------------------+
3 rows in set (0.00 sec)

আপনি হয়ে গেছেন, সদৃশ সারিগুলি সরানো হবে, শেষের টাইমস্ট্যাম্পের মাধ্যমে রাখা হবে।

আপনার কাছে টাইমস্ট্যাম্প বা অনন্য কলাম ছাড়াই।

বাছাই করার জন্য আপনার কাছে কোনও timestampবা অনন্য সূচক কলাম নেই? আপনি অধঃপতনের অবস্থায় বাস করছেন। সদৃশ সারিগুলি মোছার জন্য আপনাকে অতিরিক্ত পদক্ষেপগুলি করতে হবে।

পেঙ্গুইন টেবিল তৈরি করুন এবং কিছু সারি যুক্ত করুন

create table penguins(foo int, bar varchar(15)); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(4, 'rico'); 
select * from penguins; 
    # +------+----------+ 
    # | foo  | bar      | 
    # +------+----------+ 
    # |    1 | skipper  | 
    # |    1 | skipper  | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    4 | rico     | 
    # +------+----------+ 

প্রথম টেবিলের একটি ক্লোন তৈরি করুন এবং এতে অনুলিপি করুন।

drop table if exists penguins_copy; 
create table penguins_copy as ( SELECT foo, bar FROM penguins );  

#add an autoincrementing primary key: 
ALTER TABLE penguins_copy ADD moo int AUTO_INCREMENT PRIMARY KEY first; 

select * from penguins_copy; 
    # +-----+------+----------+ 
    # | moo | foo  | bar      | 
    # +-----+------+----------+ 
    # |   1 |    1 | skipper  | 
    # |   2 |    1 | skipper  | 
    # |   3 |    3 | kowalski | 
    # |   4 |    3 | kowalski | 
    # |   5 |    3 | kowalski | 
    # |   6 |    4 | rico     | 
    # +-----+------+----------+ 

সর্বাধিক সমষ্টি নতুন ম সূচকে পরিচালনা করে:

delete a from penguins_copy a left join( 
    select max(moo) myindex, foo, bar 
    from penguins_copy 
    group by foo, bar) b 
    on a.moo = b.myindex and 
    a.foo = b.foo and 
    a.bar = b.bar 
    where b.myindex IS NULL; 

#drop the extra column on the copied table 
alter table penguins_copy drop moo; 
select * from penguins_copy; 

#drop the first table and put the copy table back: 
drop table penguins; 
create table penguins select * from penguins_copy; 

পর্যবেক্ষণ এবং পরিষ্কার

drop table penguins_copy; 
select * from penguins;
+------+----------+ 
| foo  | bar      | 
+------+----------+ 
|    1 | skipper  | 
|    3 | kowalski | 
|    4 | rico     | 
+------+----------+ 
    Elapsed: 1458.359 milliseconds 

যে বড় এসকিউএল মুছে ফেলা বিবৃতিটি কি করছে?

ওরফে 'ক' দিয়ে টেবিল পেঙ্গুইনগুলি টেবিল পেঙ্গুইনের একটি উপসেটে যুক্ত হয়ে যায় যার নাম 'এল' বি '। ডান হাতের টেবিল 'বি' যা একটি সাবসেটটি সর্বাধিক টাইমস্ট্যাম্প [বা সর্বাধিক মূ] কলাম foo এবং বার দ্বারা গোষ্ঠীভুক্ত finds এটি বাম হাতের টেবিল 'এ' এর সাথে মেলে। (ফু, বার, বাজ) বামদিকে টেবিলে প্রতিটি সারি রয়েছে। ডান হাতের উপসেট 'বি' এর একটি (ম্যাক্সটাইমস্ট্যাম্প, ফু, বার) রয়েছে যা কেবলমাত্র সর্বাধিক আইএসের সাথে বামে মেলে।

যে সারিটি সর্বাধিক নয় সেগুলিতে NULL এর মান ম্যাক্সটাইমস্ট্যাম্প থাকে। সেই নাল সারিগুলিতে ফিল্টার করুন এবং আপনার কাছে foo এবং বার দ্বারা বিভক্ত সমস্ত সারিগুলির একটি সেট রয়েছে যা সর্বশেষতম টাইমস্ট্যাম্প বাজ নয়। সেইগুলি মুছুন।

আপনি এটি চালানোর আগে টেবিলের একটি ব্যাকআপ তৈরি করুন।

এই সমস্যাটি এই টেবিলে আবার কখনও ঘটে যাওয়া থেকে বিরত করুন:

যদি আপনি এটি কাজ করতে পারেন এবং এটি আপনার "সদৃশ সারি" আগুন ধরিয়ে দেয়। গ্রেট। আরও অনুলিপি প্রথম স্থানে যুক্ত হতে রোধ করতে আপনার টেবিলের (এই দুটি কলামে) একটি নতুন যৌগিক অনন্য কী সংজ্ঞায়িত করুন।

একটি ভাল ইমিউন সিস্টেমের মতো, খারাপ সারিগুলি সারণির সময় টেবিলে প্রবেশ করাও উচিত নয়। পরে সেই সমস্ত প্রোগ্রামগুলিতে নকল যুক্ত করা তাদের প্রতিবাদ প্রচার করবে এবং আপনি যখন এগুলি ঠিক করেন, এই সমস্যাটি আর কখনও সামনে আসে না।


6
খালি মাদাগাস্কার রেফারেন্সের জন্য রেট দিন!
মাইকেল উইগগিনস

1
এটি একটি দুর্দান্ত উত্তর এবং দুর্দান্ত পরামর্শ হিসাবে রেট দেওয়া হয়েছে, ধন্যবাদ এরিক সেখানে অন্য যে কোনও উত্তর চেয়ে ভাল কাজ করেছে।
জোহান

4
দ্রষ্টব্য: যদি আপনার টেবিলটিতে একটি অটো ইনক্রিমেন্ট IDকলাম থাকে তবে ONক্লজটি কেবলমাত্র IDকলামটির সাথে মেলে প্রয়োজন , অন্য কিছু নয়।
ebyrob

1
আমি বিস্তারিত ব্যাখ্যা পছন্দ করি তবে ... আমি যদি সঠিকভাবে বুঝতে পারি তবে এই উত্তরটি রেকর্ডগুলির মধ্যে পার্থক্য করার জন্য টাইমস্ট্যাম্পটি ব্যবহার করে। সেই অর্থে, রেকর্ডগুলি সদৃশ নয়। আপনি যদি রেকর্ডের মধ্যে পার্থক্য করার জন্য টাইমস্ট্যাম্প না পেয়ে থাকেন তবে 2 বা ততোধিক রেকর্ডের জন্য সমস্ত কলস সমান?
Rsc Rs

1
@ আরএসসিআরএসসি যদি আপনার সর্বাধিক সমষ্টি প্রয়োগের জন্য টাইমস্ট্যাম্প কলাম বা অনন্য সূচক না থাকে তবে দেখে মনে হচ্ছে আপনার টেবিলটি সদৃশ করতে হবে, একটি অনন্য সূচি যুক্ত করতে হবে, মুছুন বিবৃতিটি প্রয়োগ করুন, তারপরে অনুলিপি করা টেবিলটি মূলটিতে ফিরিয়ে আনুন । আমি এই নির্দেশাবলী প্রতিফলিত উত্তর পরিবর্তন করেছি।
এরিক লেসচিনস্কি

16

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

একটি কোয়েস্টির বিবৃতিতে, কোনও টেম্প টেবিল ছাড়াই, এটি আমার পক্ষে সবচেয়ে ভাল কাজ করেছে,

DELETE e.*
FROM employee e
WHERE id IN
 (SELECT id
   FROM (SELECT MIN(id) as id
          FROM employee e2
          GROUP BY first_name, last_name
          HAVING COUNT(*) > 1) x);

একমাত্র সতর্কতাই হ'ল আমাকে একাধিকবার ক্যোয়ারী চালাতে হবে, তবে তার সাথেও আমি খুঁজে পেয়েছি এটি অন্যান্য বিকল্পের চেয়ে আমার পক্ষে আরও ভাল কাজ করেছে।


1
ব্যবহারিক সমাধান! আমার জন্য কাজ করেছেন - 2 মি + সারির ইনোডাব টেবিলের জন্য প্রায় 20s। একবার আমি এটি কয়েকবার ব্যবহার করেছি এবং কয়েকটি সংখ্যক অপরাধীর হাতে এসেছি যেখানে উচ্চ সংখ্যার সদৃশ ছিল, নিজেই কাজটি শেষ করে দিয়েছি।
ট্রয় রে

1
এক ঝাড়ুতে আমার জন্য কাজ করেছেন, দুর্দান্ত!
মুরওয়া

কোনও কলামের সদৃশ 2x এর বেশি হলে এটি একাধিকবার কার্যকর করতে হবে
পেটআর

@ পেয়েটার এই উত্তরে বলেছে যে, "একমাত্র সতর্কতা হ'ল আমাকে একাধিকবার কোয়েরি চালাতে হবে"
সিডার

13

এটি সর্বদা আমার পক্ষে কাজ করে বলে মনে হয়:

CREATE TABLE NoDupeTable LIKE DupeTable; 
INSERT NoDupeTable SELECT * FROM DupeTable group by CommonField1,CommonFieldN;

যা প্রতিটি দ্বিপে সর্বনিম্ন আইডি রাখে এবং বাকী নন-ডুপ রেকর্ড রাখে।

আমি নিম্নলিখিতগুলিও করেছি যাতে ডুপের সমস্যাটি অপসারণের পরে আর না ঘটে:

CREATE TABLE NoDupeTable LIKE DupeTable; 
Alter table NoDupeTable Add Unique `Unique` (CommonField1,CommonField2);
INSERT IGNORE NoDupeTable SELECT * FROM DupeTable;

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

Fwd মুভিং করা দু'টি ক্ষেত্রের ভিত্তিতে কোনও সদৃশ রেকর্ড তৈরি করা অসম্ভব হয়ে পড়ে।


1
আপনি একটি প্রয়োজন হত না ORDER BYযে SELECTনিশ্চিত যা রেকর্ড আসলে তোলে আর তা হবে না NoDupeTable?
ebyrob

@ebyrob আমি বিশ্বাস করি অন্যথায় নির্দেশ না দেওয়া না হলে এটি অন্যান্য মানদণ্ডের অভাবে সর্বনিম্ন আইডি নির্বাচন করবে। অবশ্যই ORDER by ID Ascআঘাত করতে পারে না তাই আমি আমার উত্তরটি সম্পাদনা করব তবুও।
ব্যবহারকারী3649739

@ebyrob দুঃখিত আমার খারাপ। এর মাধ্যমে অর্ডার করা আমার জ্ঞানের ক্ষেত্রে এটি নির্বাচন করবে না। নির্বাচনের শেষে একটি আদেশ কেবল প্রতিটি জোড়ায় পাওয়া সর্বনিম্ন আইডি দ্বারা পাওয়া নকলকে অর্ডার করবে। পর্যায়ক্রমে আপনি একটি করতে পারেন Select Max(ID)এবং তারপরে Order by Max(ID)তবে যা যা করবে তা হ'ল sertোকানোর ক্রমটি বিপরীত। সর্বোচ্চ আইডি ধরার জন্য আমার বিশ্বাস হবে আরও জটিল নির্বাচন হিসাবে যোগ দিন, আপনি উপরের আদেশটি নির্বিশেষে আপনি নিম্ন আইডি থেকে ক্ষেত্রের মানগুলি ধরবেন।
user3649739

আসলে, নিশ্চিত না যে আমি আদেশ দিয়ে কী ভাবছিলাম। আপনি স্পষ্টভাবে চাই চাই MAX(ID)বা MIN(ID)এর পরিবর্তে কলাম নাম *মধ্যে SELECT FROM DupeTableযদিও, অন্যথায় আপনি শুধু এক পাবেন ID'এলোমেলোভাবে s। প্রকৃতপক্ষে, অনেক এসকিউএল এবং এমনকি মাইএসকিউএল কঠোরতার জন্য ধারাটিতে উল্লিখিত নয় প্রতিটি কলামে একটি সামগ্রিক ফাংশন কল করা প্রয়োজন GROUP BY
ebyrob

@ebyrob সর্বোচ্চ (ID) ন্যূনতম (আইডি) পরীক্ষা করার সময় ম্যাক্স বা মাইন্ড রেকর্ডের আইডি ফিরিয়ে দেওয়া ছাড়া কিছুই করবেন না। প্রতিটি ক্ষেত্রে একই রেকর্ড দখল করে। সুতরাং ক্ষেত্র ID,First,Last,Notesএবং রেকর্ড সহ আমার যদি দুটি রেকর্ড থাকে 1,Bob,Smith,NULLএবং 2,Bob,Smith,Arrearsতারপরে একটি করে SELECT *Max(ID), First,Last,Notes FROM DupeTable group by First,Lastউভয়ই আলাদা আইডি ব্যতীত একই রেকর্ড 1 প্রদান করে। সর্বাধিক (আইডি) ফিরে আসত 2,Bob,Smith,NULLএবং মিন (আইডি) ফিরে আসত 1,Bob,Smith,NULL। নোটগুলিতে 'বকেয়া' সহ দ্বিতীয় রেকর্ড পেতে আমার বিশ্বাস হিসাবে একটি যোগদানের প্রয়োজন।
ব্যবহারকারী3649739

7

নিম্নলিখিত সমস্ত টেবিলের জন্য কাজ করে

CREATE TABLE `noDup` LIKE `Dup` ;
INSERT `noDup` SELECT DISTINCT * FROM `Dup` ;
DROP TABLE `Dup` ;
ALTER TABLE `noDup` RENAME `Dup` ;

6

এখানে একটি সহজ উত্তর:

delete a from target_table a left JOIN (select max(id_field) as id, field_being_repeated  
    from target_table GROUP BY field_being_repeated) b 
    on a.field_being_repeated = b.field_being_repeated
      and a.id_field = b.id_field
    where b.id_field is null;

এটি একটি ভাল উত্তর, একটি ছোট ভুল বাদেand a.id_field = b.id
বিক্রান্ত গোয়েল

LEFT JOINথেকে bশুধুমাত্র তুলনা করতে হবে b.id= a.id_fieldঅভিমানী field_idএকটি অনন্য স্বয়ং বৃদ্ধি আইডি নয়। তাই a.field_being_repeated = b.field_being_repeatedবিদেশী হয়। (এছাড়াও b.id_fieldএই প্রশ্নের সাথে এটা বিদ্যমান নেই b.id
ebyrob

6

পুরানো রেকর্ডগুলি সরিয়ে দেওয়ার জন্য এটি আমার পক্ষে কাজ:

delete from table where id in 
(select min(e.id)
    from (select * from table) e 
    group by column1, column2
    having count(*) > 1
); 

আপনি সর্বাধিক (e.id) থেকে সর্বাধিক (e.id) প্রতিস্থাপন করতে পারেন নতুন রেকর্ডগুলি সরাতে।



5

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

আমি আমার মন্তব্যে যেমন বলেছি, সেই সমাধানটি যদিও সঠিকভাবে ব্যাখ্যা করা হয়নি। সুতরাং এটি আমার, এটি ভিত্তিক।

1) একটি নতুন বুলিয়ান কলাম যুক্ত করুন

alter table mytable add tokeep boolean;

2) সদৃশ কলাম এবং নতুন কলামে একটি সীমাবদ্ধতা যুক্ত করুন

alter table mytable add constraint preventdupe unique (mycol1, mycol2, tokeep);

3) বুলিয়ান কলামটি সত্য হিসাবে সেট করুন। এটি নতুন প্রতিবন্ধকতার কারণে কেবলমাত্র নকল করা সারিতে একটিতে সফল হবে

update ignore mytable set tokeep = true;

৪) সারিগুলি মুছে ফেলুন যেগুলি টোপ হিসাবে চিহ্নিত করা হয়নি

delete from mytable where tokeep is null;

5) যুক্ত কলামটি বাদ দিন

alter table mytable drop tokeep;

আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি যুক্ত হওয়া সীমাবদ্ধতাটি রাখুন, যাতে ভবিষ্যতে নতুন সদৃশগুলি প্রতিরোধ করা হয়।


4

এই পদ্ধতিটি সর্বশেষ নকলটি রেখে একটি সারণীতে সমস্ত সদৃশ (Incl গুণক) সরিয়ে ফেলবে। এটি প্রতিটি গ্রুপের সর্বশেষ রেকর্ড পুনরুদ্ধার করার একটি এক্সটেনশন

আশা করি এটি কারও কাজে লাগবে।

DROP TABLE IF EXISTS UniqueIDs;
CREATE Temporary table UniqueIDs (id Int(11));

INSERT INTO UniqueIDs
    (SELECT T1.ID FROM Table T1 LEFT JOIN Table T2 ON
    (T1.Field1 = T2.Field1 AND T1.Field2 = T2.Field2 #Comparison Fields 
    AND T1.ID < T2.ID)
    WHERE T2.ID IS NULL);

DELETE FROM Table WHERE id NOT IN (SELECT ID FROM UniqueIDs);

4

আর একটি সহজ উপায় ... আপডেট ইগনোর ব্যবহার করে:

আপনাকে এক বা একাধিক কলামে (সূচক টাইপ) সূচি ব্যবহার করতে হবে। একটি নতুন অস্থায়ী রেফারেন্স কলাম তৈরি করুন (সূচকের অংশ নয়)। এই কলামে, আপনি অজানা ক্লজটি এটিকে আপডেট করে অজানাগুলি চিহ্নিত করেন। ধাপে ধাপে:

অভাবগুলি চিহ্নিত করতে একটি অস্থায়ী রেফারেন্স কলাম যুক্ত করুন:

ALTER TABLE `yourtable` ADD `unique` VARCHAR(3) NOT NULL AFTER `lastcolname`;

=> এটি আপনার টেবিলটিতে একটি কলাম যুক্ত করবে।

টেবিলটি আপডেট করুন, সবকিছুকে অনন্য হিসাবে চিহ্নিত করার চেষ্টা করুন, তবে কী সমস্যাটির নকল হওয়ার কারণে সম্ভাব্য ত্রুটিগুলি উপেক্ষা করুন (রেকর্ডগুলি এড়িয়ে যাবে):

UPDATE IGNORE `yourtable` SET `unique` = 'Yes' WHERE 1;

=> আপনি দেখতে পাবেন যে আপনার সদৃশ রেকর্ডগুলি অনন্য = 'হ্যাঁ' হিসাবে চিহ্নিত করা হবে না, অন্য কথায় ডুপ্লিকেট রেকর্ডের প্রতিটি সেটগুলির মধ্যে একটিরও অনন্য হিসাবে চিহ্নিত করা হবে।

অনন্য নয় এমন সবকিছু মুছুন:

DELETE * FROM `yourtable` WHERE `unique` <> 'Yes';

=> এটি সমস্ত সদৃশ রেকর্ড সরিয়ে ফেলবে।

কলামটি ফেলে দিন ...

ALTER TABLE `yourtable` DROP `unique`;

আমি মনে করি এটি সেরা সমাধান কারণ এটি টেবিলগুলির সাথে জগাখিচুবি করে না এবং এটি সরল সরল স্কয়ার ব্যবহার করে। একটি মাত্র বিষয় পরিষ্কার করা উচিত: uniqueকলামটি বর্তমানে অনুলিপিযুক্ত কলামগুলির সাথে এক অনন্য বাধা যুক্ত হওয়া উচিত , অন্যথায় পুরো জিনিসটি কাজ করে না কারণ SET unique= 'হ্যাঁ' কখনই ব্যর্থ হয় না।
xian

এছাড়াও সচেতন থাকুন যে uniqueএটি একটি মাইএসকিএল কীওয়ার্ড। সুতরাং এটির ব্যাকটিকস থাকতে হবে (ইতিমধ্যে সঠিকভাবে প্রদর্শিত হয়েছে)। কলামের জন্য অন্য শব্দ ব্যবহার করা আরও সুবিধাজনক হতে পারে।
টর্স্টেন

2

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

আলী , আপনার ক্ষেত্রে, আপনি এই জাতীয় কিছু চালাতে পারেন:

-- create a new temporary table
CREATE TABLE tmp_table1 LIKE table1;

-- add a unique constraint    
ALTER TABLE tmp_table1 ADD UNIQUE(sid, title);

-- scan over the table to insert entries
INSERT IGNORE INTO tmp_table1 SELECT * FROM table1 ORDER BY sid;

-- rename tables
RENAME TABLE table1 TO backup_table1, tmp_table1 TO table1;

0
delete from `table` where `table`.`SID` in 
    (
    select t.SID from table t join table t1 on t.title = t1.title  where t.SID > t1.SID
)

এটি মাইএসকিউএলের কয়েকটি কনফিগারেশন এবং সংস্করণগুলিতে এসকিউএল ত্রুটি (1093) উত্পন্ন করে।
ebyrob

0

@ এরিকের উত্তরকে ভালবাসুন তবে আপনার যদি সত্যিই বড় টেবিল থাকে ( The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okayএটি চালানোর চেষ্টা করার সময় আমি পেয়ে যাচ্ছি ) তবে এটি কার্যকর হবে বলে মনে হচ্ছে না । সুতরাং আমি যোগদানের ক্যোয়ারীটি কেবলমাত্র সদৃশ সারিগুলি বিবেচনা করতে সীমাবদ্ধ করেছি এবং এর সাথে আমি শেষ করেছি:

DELETE a FROM penguins a
    LEFT JOIN (SELECT COUNT(baz) AS num, MIN(baz) AS keepBaz, foo
        FROM penguins
        GROUP BY deviceId HAVING num > 1) b
        ON a.baz != b.keepBaz
        AND a.foo = b.foo
    WHERE b.foo IS NOT NULL

এই ক্ষেত্রে WHWEE ধারাটি মাইএসকিউএলকে এমন কোনও সারি উপেক্ষা করতে দেয় যার ডুপ্লিকেট নেই এবং এটি এটিকেও অনুলিপি করবে যদি এটি অনুলিপিটির প্রথম উদাহরণ তাই কেবল পরবর্তী ডুপ্লিকেটগুলি উপেক্ষা করা হবে। পরিবর্তন MIN(baz)করার জন্য MAX(baz)প্রথমে পরিবর্তে গত উদাহরণস্বরূপ রাখা।


0

এটি বড় টেবিলগুলির জন্য কাজ করে:

 CREATE Temporary table duplicates AS select max(id) as id, url from links group by url having count(*) > 1;

 DELETE l from links l inner join duplicates ld on ld.id = l.id WHERE ld.id IS NOT NULL;

প্রাচীনতম পরিবর্তন মুছে ফেলার জন্য max(id)করতেmin(id)


0

এটি এখানে কলামটিকে column_nameপ্রাথমিক কী হিসাবে তৈরি করবে এবং এর মধ্যে সমস্ত ত্রুটি উপেক্ষা করবে। সুতরাং এটির জন্য সদৃশ মান সহ সারিগুলি মুছবে column_name

ALTER IGNORE TABLE `table_name` ADD PRIMARY KEY (`column_name`);

পূর্বের উত্তরের মন্তব্যে যেমন উল্লেখ করা হয়েছে, এটি আর 5.7-এ কাজ করে না।
বার্মার

0

আমি মনে করি এটি মূলত টেবিলটি অনুলিপি করে খালি করে কাজ করবে তবে কেবলমাত্র স্বতন্ত্র মানগুলিকেই এটির মধ্যে ফিরিয়ে রাখুন তবে দয়া করে এটি প্রচুর পরিমাণে ডেটা করার আগে ডাবল পরীক্ষা করে দেখুন।

আপনার টেবিলের একটি কার্বন অনুলিপি তৈরি করে

পুরানো টেবিলের মতো টেবিল টেম্পলেট করুন; পুরাতন টেবিল নাম থেকে টেম্প টেবিল সন্নিবেশ করান;

আপনার মূল টেবিলটি খালি করে

পুরাতন নাম থেকে * মুছে ফেলুন;

অনুলিপি করা টেবিল থেকে সমস্ত স্বতন্ত্র মানগুলি আপনার মূল সারণীতে ফিরে যায়

প্রথম নাম, শেষ নাম, দোব দ্বারা অস্থায়ী_ টেবিল গোষ্ঠী থেকে পুরাতন টেবিল নাম নির্বাচন করুন

আপনার টেম্প টেবিল মুছে ফেলে।

টেবিল অস্থায়ী_ টেবিল ড্রপ

আপনি পৃথক রাখতে চান এমন সমস্ত এলএল ক্ষেত্রগুলির দ্বারা আপনার গোষ্ঠী তৈরি করতে হবে।


0
DELETE T2
FROM   table_name T1
JOIN   same_table_name T2 ON (T1.title = T2.title AND T1.ID <> T2.ID)

এটি আপনার অনুরোধটি কার্যকর করে না, দয়া করে আপনি এটি উন্নত করতে পারেন?
সমীর গাইড

0

এখানে আমি সাধারণত নকলগুলি অপসারণ করি

  1. একটি অস্থায়ী কলাম যুক্ত করুন, যা খুশি নাম দিন (আমি সক্রিয় হিসাবে উল্লেখ করব)
  2. যে ক্ষেত্রগুলিকে আপনি সদৃশ হওয়ার কথা না বলে মনে করেন এবং তাদের অ্যাক্টিভেটিকে 1 এ সেট করা উচিত সেগুলি অনুসারে গ্রুপ করুন, সেই কলামগুলির জন্য কেবলমাত্র একটি সদৃশ মান বেছে নেবে (সদৃশ নির্বাচন করবে না)
  3. সক্রিয় শূন্যযুক্তগুলি মুছুন
  4. ড্রপ কলাম সক্রিয়
  5. allyচ্ছিকভাবে (যদি আপনার উদ্দেশ্যগুলির সাথে মানানসই হয়), সেই কলামগুলির জন্য আবার অনুলিপি না দেওয়ার জন্য অনন্য সূচক যুক্ত করুন

-2

আপনি শুধু (এবং "পরিষ্কার" তালিকা নির্বাচন করার জন্য একটি স্বতন্ত্র ধারা ব্যবহার করতে পারে এখানে যে কাজ করতে কিভাবে একটি খুব সহজ উদাহরণ)।


কিভাবে যে প্রশ্নের উত্তর দেয়? DISTINCTআপনাকে প্রথমে থাকা নকলগুলি সম্পর্কে কোনও তথ্য শিথিল করে । আপনি এটি ব্যবহার করে সদৃশ মুছতে একটি উপায় প্রদর্শন করতে পারেন?
luk2302

-3

আপনি যদি এগুলি গণনা করেন তবে কী এটি কাজ করতে পারে এবং তারপরে আপনার মোছা ক্যোয়ারিতে মাত্র একটি রেখে একটি সীমা যুক্ত করবেন?

উদাহরণস্বরূপ, আপনার যদি দু'একটি বেশি থাকে তবে আপনার ক্যোয়ারীটি এভাবে লিখুন:

DELETE FROM table WHERE SID = 1 LIMIT 1;

-5

আপনার টেবিল থেকে সদৃশ ডেটা সরানোর সময় কয়েকটি প্রাথমিক পদক্ষেপ রয়েছে:

  • আপনার টেবিল ব্যাক আপ!
  • সদৃশ সারিগুলি সন্ধান করুন
  • সদৃশ সারিগুলি সরান

এখানে পুরো টিউটোরিয়ালটি রয়েছে: https://blog.teamsql.io/deleting-dusedate-data-3541485b3473


শুধুমাত্র অনন্য আইডি আলাদা হলে এটি কাজ করে? ইয়ার সাদেস বেনজার্সিজ আইডি ফরক্লি ইসে দে বু আইয়ার ইয়ার মি?
অ্যান্ড্রু

ডিফল্টরূপে এখানে বর্ণিত পদ্ধতিটি মাইএসকিউএল সংস্করণ> 5.7.5 এর জন্য কাজ করে না। এটি হ'ল কেবলমাত্র_এইচএল_ফুল_জিগ্রুপ_বি পরিচালনা করার কারণে। এখানে দেখুন: dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
delatbabel
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.