মাইএসকিউএলে সদৃশ রেকর্ডগুলি সন্ধান করুন


650

আমি একটি মাইএসকিউএল ডেটাবেসে নকল রেকর্ডগুলি বের করতে চাই। এটি দিয়ে করা যেতে পারে:

SELECT address, count(id) as cnt FROM list
GROUP BY address HAVING cnt > 1

যার ফলাফল:

100 MAIN ST    2

আমি এটি টানতে চাই যাতে এটি প্রতিটি সারি দেখায় যা সদৃশ। কিছুটা এইরকম:

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST

এটি কীভাবে করা যায় সে সম্পর্কে কোনও চিন্তাভাবনা? আমি প্রথমটি করা এড়ানোর চেষ্টা করছি তারপরে কোডে দ্বিতীয় ক্যোয়ারী সহ নকলগুলি সন্ধান করা।

উত্তর:


684

কীটি হ'ল এই ক্যোয়ারীটি পুনর্লিখন করা যাতে এটি সাবকিউরি হিসাবে ব্যবহার করা যায়।

SELECT firstname, 
   lastname, 
   list.address 
FROM list
   INNER JOIN (SELECT address
               FROM   list
               GROUP  BY address
               HAVING COUNT(id) > 1) dup
           ON list.address = dup.address;

69
সাব-কোয়েরিতে সতর্ক থাকুন। পারফরম্যান্স উদ্বেগের জন্য উপ-প্রশ্নগুলি হাস্যকরভাবে খারাপ হতে পারে। যদি এটি প্রায়শই এবং / অথবা প্রচুর নকল রেকর্ডের সাথে ঘটে থাকে তবে আমি প্রসেসিংটি ডেটাবেস থেকে বের করে একটি ডেটাসেটে সরিয়ে নেওয়ার বিষয়টি বিবেচনা করব।
বিডওয়াকফিল্ড 19

11
এটি একটি নিরবিচ্ছিন্ন সাবকোয়ারি, সুতরাং একা কোয়েরিটি খুব খারাপভাবে ডিজাইন করা হয়নি তা ধরে নিয়ে খুব খারাপ হওয়া উচিত নয়।
12u

বাহ। অনুমান করুন এটি "ERROR 1248 (42000) এর চারপাশের সিনট্যাক্স: প্রতিটি
উত্সযুক্ত

3
এটি সঠিক ধারণা, তবে আবার নীচের মত, এটি কেবল তখনই কাজ করে যদি ঠিকানাগুলি মানক হওয়ার নিশ্চয়তা দেওয়া হয় ...
ম্যাট

30
এই কোয়েরির সাহায্যে +1 আপনি নকল পেতে পারেন তবে
ত্রিভুজ

352
SELECT date FROM logs group by date having count(*) >= 2

5
লারাভেলের সাথে ব্যবহার করার জন্য এটি সবচেয়ে সহজ কার্যকারী ক্যোয়ারী ছিল। শুধু ->having(DB::raw('count(*)'), '>', 2)ক্যোয়ারিতে যুক্ত করতে হয়েছিল। অনেক ধন্যবাদ!
কোভ

1
10 মিলিয়ন সারি টেবিল দিয়ে ভাল কাজ করে। এটি সেরা উত্তর হওয়া উচিত
টেরি লিন

13
এই উত্তরটি সম্পর্কে সতর্কতা অবলম্বন করুন। এটি প্রতিলিপিগুলির মধ্যে একটিরই ফিরে আসে। যদি আপনার কাছে একই রেকর্ডের 2 টিরও বেশি অনুলিপি থাকে তবে আপনি সেগুলি দেখতে পাবেন না এবং রেকর্ডটি ফিরিয়ে দেওয়ার পরেও আপনার টেবিলটিতে নকল থাকবে।
মিকিকো জেন

7
কেন >=2? কেবলমাত্র ব্যবহার করুনHAVING COUNT(*) > 1
BadHorsie

2
@ টেরিলিন বিবেচনা করে যে এটি প্রকৃতপক্ষে বর্ণিত সমস্যাটি সমাধান করে না (যা ছিল কীভাবে সমস্ত অনুলিপি ফিরিয়ে দিতে হবে) আমি একমত নই।
মাইকেল

198

কেন কেবল নিজের সাথে টেবিলের সাথে অন্তর্ভুক্ত হবে না?

SELECT a.firstname, a.lastname, a.address
FROM list a
INNER JOIN list b ON a.address = b.address
WHERE a.id <> b.id

যদি ঠিকানাটি দু'বারের বেশি থাকতে পারে তবে একটি DISTINCT প্রয়োজন।


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

4
আমি ক্যোয়ারির শেষ অংশটি পরিবর্তন করে WHERE a.id > b.idকেবল নতুন ডুপ্লিকেটগুলি ফিল্টার করতে পেরেছি, সেভাবে আমি DELETEফলাফলটিতে সরাসরি করতে পারি । পুরানো নকলগুলি তালিকার তুলনায় স্যুইচ করুন।
Stoffe

1
এটি চলতে 50 সেকেন্ড সময় নিয়েছে, @ ডাবল জোশের উত্তর .13 সেকেন্ড সময় নিয়েছে।
অ্যান্টোনেস্টাম

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

আমি এটি লেটকোড " লেটকোড / প্রব্লেমস / ডুপ্লিকেট- ইমেলস" এ পরীক্ষা করেছি । এটি সাব-কোয়েরির সাথে তুলনা করে দ্রুত ছিল।
বিলো

56

আমি এই প্রশ্নের জন্য বেছে নেওয়া সেরা উত্তর চেষ্টা করেছি, কিন্তু এটি আমাকে কিছুটা বিভ্রান্ত করেছে। আমি আসলে আমার টেবিল থেকে একটি একা মাঠে এটি প্রয়োজন। এই লিঙ্ক থেকে নিম্নলিখিত উদাহরণটি আমার জন্য খুব ভাল কাজ করেছে:

SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;

একটি যাদুমন্ত্র মত কাজ করে!
Vinícius

47
select `cityname` from `codcities` group by `cityname` having count(*)>=2

এটি আপনার অনুরোধের অনুরূপ ক্যোয়ারী এবং এটির 200% কাজ করা এবং সহজ। উপভোগ করুন !!!


37

এটি কি সহজ নয়:

SELECT *
FROM tc_tariff_groups
GROUP BY group_id
HAVING COUNT(group_id) >1

?


1
আমার জন্য কাজ করেছিল যেখানে আমাকে মাত্র 600 ডলার সদৃশ সারিগুলি অনন্য করতে করতে প্রসেস করতে হয়েছিল, সমস্ত 600 000 সারি লোডের চেয়ে অনেক দ্রুত।
অ্যাড্রিয়ানটিএনটি

1
খুব সহজ
শ্বেত

35

এই প্রশ্নের সাথে ইমেল ঠিকানার মাধ্যমে সদৃশ ব্যবহারকারীদের সন্ধান করুন ...

SELECT users.name, users.uid, users.mail, from_unixtime(created)
FROM users
INNER JOIN (
  SELECT mail
  FROM users
  GROUP BY mail
  HAVING count(mail) > 1
) dupes ON users.mail = dupes.mail
ORDER BY users.mail;

2
আসল সদৃশটি সন্ধান করতে আপনার কেবল অভ্যন্তরীণ কোয়েরি প্রয়োজন। এটি অন্যান্য উত্তরের চেয়ে দ্রুত গতিতে।
অ্যান্টোনেস্টাম

20

আমরা খুঁজে পেয়েছি যে নকলগুলি আরও একটি ক্ষেত্রের উপর নির্ভর করে those এই ক্ষেত্রে আপনি নীচের ফর্ম্যাটটি ব্যবহার করতে পারেন।

SELECT COUNT(*), column1, column2 
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;

16

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

আমি স্মার্টস্ট্রিটসে কাজ করি , যেখানে আমরা বৈধতা এবং ডি-ডুপ্লিকেশন এবং অন্যান্য জিনিসগুলিকে করি এবং অনুরূপ সমস্যার সাথে আমি প্রচুর বিচিত্র চ্যালেঞ্জ দেখেছি।

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

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


6
অ্যাড্রেস স্ট্রিংগুলির সাথে ম্যাচ করাতে অসুবিধা দেখার জন্য +1, যদিও আপনি উল্লেখ করতে পারেন যে ওপির "নকল রেকর্ড" প্রশ্নটি নিজের মধ্যে জটিল নয়, তবে ঠিকানার সাথে তুলনা করার সময়
গল্পের

13

আর একটি সমাধান হ'ল টেবিলের মতো ব্যবহার যেমন:

SELECT p1.id, p2.id, p1.address
FROM list AS p1, list AS p2
WHERE p1.address = p2.address
AND p1.id != p2.id

এই ক্ষেত্রে আপনি যা করছেন তা হ'ল মূল তালিকা টেবিলটি গ্রহণ করা, এর মধ্যে দুটি পি রেটেড টেবিল তৈরি করা - পি 1 এবং পি 2 - এবং এর পরে ঠিকানা কলামে (লাইন 3) একটি যোগদান সম্পাদন করা। 4 র্থ লাইনটি নিশ্চিত করে যে আপনার ফলাফলের সেটগুলিতে একই রেকর্ড একাধিকবার প্রদর্শিত হবে না ("ডুপ্লিকেট নকল")।


1
সুন্দর কাজ করে যদি WHIE LIKE এর সাথে চেক করছে তবে অ্যাডাস্ট্রোফগুলিও পাওয়া যাবে। ক্যোয়ারীটি ধীর করে দেয় তবে আমার ক্ষেত্রে এটি একটি ওয়ান টাইমার।
গসি

10

খুব দক্ষ হতে যাচ্ছে না, তবে এটি কাজ করা উচিত:

SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;

10

এটি একটি টেবিল পাসে নকল নির্বাচন করবে, কোনও সাবকিউরি নয়।

SELECT  *
FROM    (
        SELECT  ao.*, (@r := @r + 1) AS rn
        FROM    (
                SELECT  @_address := 'N'
                ) vars,
                (
                SELECT  *
                FROM
                        list a
                ORDER BY
                        address, id
                ) ao
        WHERE   CASE WHEN @_address <> address THEN @r := 0 ELSE 0 END IS NOT NULL
                AND (@_address := address ) IS NOT NULL
        ) aoo
WHERE   rn > 1

এই প্রশ্নের সাথে actially অনুকরণ ROW_NUMBER()বর্তমানে OracleএবংSQL Server

বিস্তারিত জানতে আমার ব্লগে নিবন্ধটি দেখুন:


20
নিটপিকের জন্য নয়, FROM (SELECT ...) aooএটি একটি সাবকোয়ারি :
রকেট

8

এটি আপনাকে দেখায় যে কয়টি সদৃশ রয়েছে এবং যোগদানের ছাড়াই ফলাফল অর্ডার করবে

SELECT  `Language` , id, COUNT( id ) AS how_many
FROM  `languages` 
GROUP BY  `Language` 
HAVING how_many >=2
ORDER BY how_many DESC

নিখুঁত কারণ এটি এখনও বলে যে কতগুলি এন্ট্রিগুলি নকল করা হয়েছে
ড্যানিস

4
 SELECT firstname, lastname, address FROM list
 WHERE 
 Address in 
 (SELECT address FROM list
 GROUP BY address
 HAVING count(*) > 1)

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

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

আমি চিন্তিত ছিলাম কলামের পরিবর্তে কমা দ্বারা পৃথক করা তালিকা প্রয়োজন, যা কেবল ভুল ছিল। এখানে আমার কাছে কাজ করা ক্যোয়ারীটি রয়েছে:SELECT users.name, users.uid, users.mail, from_unixtime(created) FROM users INNER JOIN ( SELECT mail FROM users GROUP BY mail HAVING count(mail) > 1 ) dup ON users.mail = dup.mail ORDER BY users.mail, users.created;
ডাবল জোশ

4
select * from table_name t1 inner join (select distinct <attribute list> from table_name as temp)t2 where t1.attribute_name = t2.attribute_name

আপনার টেবিলের জন্য এটি এমন কিছু হবে

select * from list l1 inner join (select distinct address from list as list2)l2 where l1.address=l2.address

এই ক্যোয়ারীটি আপনাকে আপনার তালিকার টেবিলে সমস্ত স্বতন্ত্র ঠিকানা এন্ট্রি দেবে ... আমি নিশ্চিত নই যে আপনার যদি নামের জন্য কোনও প্রাথমিক কী মান থাকে তবে এটি কীভাবে কাজ করবে ..


4

দ্রুততম সদৃশগুলি মুছে ফেলার প্রশ্নের পদ্ধতি:

/* create temp table with one primary column id */
INSERT INTO temp(id) SELECT MIN(id) FROM list GROUP BY (isbn) HAVING COUNT(*)>1;
DELETE FROM list WHERE id IN (SELECT id FROM temp);
DELETE FROM temp;

2
এটি অবশ্যই প্রতিটি নকলের গ্রুপ থেকে প্রথম রেকর্ড মুছে ফেলবে।
প্লেক

4

ব্যক্তিগতভাবে এই ক্যোয়ারীটি আমার সমস্যার সমাধান করেছে:

SELECT `SUB_ID`, COUNT(SRV_KW_ID) as subscriptions FROM `SUB_SUBSCR` group by SUB_ID, SRV_KW_ID HAVING subscriptions > 1;

এই স্ক্রিপ্টটি যা করে তা হ'ল সমস্ত গ্রাহক আইডির টেবিলের মধ্যে একাধিকবার উপস্থিত এবং নকলের সন্ধান পাওয়া যায়।

এটি টেবিল কলাম:

| SUB_SUBSCR_ID | int(11)     | NO   | PRI | NULL    | auto_increment |
| MSI_ALIAS     | varchar(64) | YES  | UNI | NULL    |                |
| SUB_ID        | int(11)     | NO   | MUL | NULL    |                |    
| SRV_KW_ID     | int(11)     | NO   | MUL | NULL    |                |

আশা করি এটি আপনার পক্ষেও সহায়ক হবে!


3
SELECT t.*,(select count(*) from city as tt where tt.name=t.name) as count FROM `city` as t where (select count(*) from city as tt where tt.name=t.name) > 1 order by count desc

আপনার টেবিল দিয়ে শহরটি প্রতিস্থাপন করুন । আপনার ক্ষেত্রের নামের সাথে নামটি প্রতিস্থাপন করুন



0
    Find duplicate Records:

    Suppose we have table : Student 
    student_id int
    student_name varchar
    Records:
    +------------+---------------------+
    | student_id | student_name        |
    +------------+---------------------+
    |        101 | usman               |
    |        101 | usman               |
    |        101 | usman               |
    |        102 | usmanyaqoob         |
    |        103 | muhammadusmanyaqoob |
    |        103 | muhammadusmanyaqoob |
    +------------+---------------------+

    Now we want to see duplicate records
    Use this query:


   select student_name,student_id ,count(*) c from student group by student_id,student_name having c>1;

+--------------------+------------+---+
| student_name        | student_id | c |
+---------------------+------------+---+
| usman               |        101 | 3 |
| muhammadusmanyaqoob |        103 | 2 |
+---------------------+------------+---+

0

সদৃশ সারিগুলি দ্রুত দেখতে আপনি একটি একক সাধারণ ক্যোয়ারী চালাতে পারেন

এখানে আমি টেবিলটি জিজ্ঞাসা করছি এবং একই ব্যবহারকারীর ID, মার্কেটপ্লেস এবং স্কুর সাথে সমস্ত নকল সারি তালিকাবদ্ধ করছি:

select user_id, market_place,sku, count(id)as totals from sku_analytics group by user_id, market_place,sku having count(id)>1;

সদৃশ সারি মুছতে আপনি কোন সারিটি মুছতে চান তা সিদ্ধান্ত নিতে হবে। যেমন নিম্ন আইডি সহ একটি (সাধারণত পুরানো) বা অন্য কোনও তারিখের তথ্য থাকতে পারে। আমার ক্ষেত্রে আমি কেবলমাত্র নিম্ন আইডিটি মুছতে চাই কারণ নতুন আইডি সর্বশেষ তথ্য।

প্রথমে ডাবল চেক করুন যদি সঠিক রেকর্ডগুলি মুছে ফেলা হয়। এখানে আমি নকলগুলির মধ্যে রেকর্ড নির্বাচন করছি যা মুছে ফেলা হবে (অনন্য আইডি দ্বারা)।

select a.user_id, a.market_place,a.sku from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

তারপরে আমি ডুপগুলি মুছতে মুছুন কোয়েরিটি চালাব:

delete a from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

ব্যাকআপ, ডাবল চেক, যাচাইকরণ, ব্যাকআপ যাচাই করুন তারপর সম্পাদন করুন।


-1

select address from list where address = any (select address from (select address, count(id) cnt from list group by address having cnt > 1 ) as t1) order by address

অভ্যন্তরীণ সাব-কোয়েরিটি সদৃশ ঠিকানার সাথে সারিগুলি দেয় এবং তারপরে বহিরাগত সাব-কোয়েরি সদৃশগুলির সাথে ঠিকানার জন্য ঠিকানা কলামটি দেয়। বহিরাগত সাব-কোয়েরিতে অবশ্যই একটি কলাম অবশ্যই ফিরবে কারণ এটি অপারেটর হিসাবে অপারেন্ড হিসাবে ব্যবহৃত হয়েছে '= যেকোন'


-1

পাওয়ারলর্ড উত্তরটি প্রকৃতপক্ষে সেরা এবং আমি আরও একটি পরিবর্তনের সুপারিশ করব: ডিবি অতিরিক্ত লোড না হয়ে যায় তা নিশ্চিত করতে LIMIT টি ব্যবহার করুন:

SELECT firstname, lastname, list.address FROM list
INNER JOIN (SELECT address FROM list
GROUP BY address HAVING count(id) > 1) dup ON list.address = dup.address
LIMIT 10

যেখানে কোথায় নেই এবং যখন যোগদানের সময় লিমিটেড ব্যবহার করা ভাল অভ্যাস। ছোট মান দিয়ে শুরু করুন, কোয়েরিটি কতটা ভারী তা পরীক্ষা করুন এবং তারপরে সীমাটি বাড়ান।


এটি কীভাবে কোনও কিছুতে অবদান রাখছে?
কেনেট সেলেস্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.