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


769

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


1
যেহেতু আপনি সমস্ত রেকর্ড সন্ধানের উল্লেখ করেছেন, তাই আমি ধরে নিচ্ছি যে আপনার ভার্সার কলামে KEYS পাশাপাশি নকল ভ্যালুগুলিও জানতে হবে।
টেকট্রাভেলথিংক

মানগুলি পাওয়ার পরে আমি কীগুলি সহজেই সন্ধান করতে পারি, সত্যই আমি কেবল সমস্ত সদৃশ মানগুলির একটি তালিকা চাই।
জন টেকাবুরি

উত্তর:


1520

একটি কি SELECTএকটি সঙ্গে GROUP BYদফা। আসুন যাক নামটি হ'ল কলামটিই আপনি অনুলিপি খুঁজে পেতে চান:

SELECT name, COUNT(*) c FROM table GROUP BY name HAVING c > 1;

এটি প্রথম কলামে নামের মান সহ ফলাফলটি ফিরে আসবে এবং দ্বিতীয়টিতে সেই মানটি কতবার প্রদর্শিত হবে তার একটি গণনা।


27
তবে ডুপ্লিকেট মান সহ সারিগুলির আইডি না পেলে এটি কীভাবে কার্যকর? হ্যাঁ, আপনি প্রতিটি সদৃশ মানের জন্য একটি নতুন কোয়েরি মিলিয়ে করতে পারেন, তবে কেবল নকলগুলি তালিকাভুক্ত করা কি সম্ভব?
নোবেলপ্লিট

23
@ NobleUplift আপনি এটি করতে পারেন GROUP_CONCAT(id)এবং এটি আইডি তালিকাভুক্ত করবে। একটি উদাহরণের জন্য আমার উত্তর দেখুন।
ম্যাট রার্ডন

5
এর অর্থ কী হবে ERROR: column "c" does not exist LINE 1?
ব্যবহারকারী

15
আমি কেন বিভ্রান্তি বোধ করি কেন এটি গৃহীত উত্তর এবং কেন এটির এতগুলি উত্সাহ রয়েছে। ওপি জিজ্ঞাসা করেছিল, "আমি এই কলামে নকল মান রয়েছে এমন সমস্ত রেকর্ড সন্ধান করতে চাই" " এই উত্তর গণনা একটি সারণী ফেরত। -1
মনিকা হেডনেক

4
যারা কীভাবে কাজ করে তা বোঝেন না - এটি কেবলমাত্র ফলাফলের সেটটিতে একটি ফিল্টার, তাই মূল ক্যোয়ারির পরে ঘটে।
জন হান্ট

236
SELECT varchar_col
FROM table
GROUP BY varchar_col
HAVING COUNT(*) > 1;

10
@ লেভিকের উত্তরের চেয়ে উচ্চতর কারণ এটি কোনও অতিরিক্ত কলাম যুক্ত করে না। IN()/ এর সাথে ব্যবহারের জন্য এটি দরকারী করে তোলে NOT IN()
wmassingham

172
SELECT  *
FROM    mytable mto
WHERE   EXISTS
        (
        SELECT  1
        FROM    mytable mti
        WHERE   mti.varchar_column = mto.varchar_column
        LIMIT 1, 1
        )

এই কোয়েরিটি কেবল স্বতন্ত্র নয়, সম্পূর্ণ রেকর্ডগুলি দেয় varchar_column

এই কোয়েরিটি ব্যবহার করে না COUNT(*)। যদি প্রচুর অনুলিপি থাকে, COUNT(*)ব্যয়বহুল এবং আপনার পুরোটির প্রয়োজন নেই COUNT(*), আপনার কেবল একই মান সহ দুটি সারি রয়েছে কিনা তা জানতে হবে।

varchar_columnইচ্ছার উপর একটি সূচক থাকা অবশ্যই অবশ্যই এই ক্যোয়ারিকে ব্যাপকভাবে গতিবেগ করুন।


3
খুব ভালো. আমি ORDER BY varchar_column DESCক্যোয়ারির শেষে যুক্ত করেছি ।
28:25 '

8
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত, GROUP BYএবং HAVINGসম্ভাব্য সদৃশগুলির মধ্যে কেবল একটিরই প্রত্যাবর্তন। এছাড়াও, পরিবর্তে সূচকযুক্ত ক্ষেত্রের সাথে পারফরম্যান্স COUNT(*)এবং ORDER BYনকল রেকর্ডকে গোষ্ঠী করার সম্ভাবনা ।
রামি

1
উপরের মন্তব্যগুলিতে যেমন বলা হয়েছে, এই ক্যোয়ারী আপনাকে সমস্ত সদৃশ সারি তালিকাভুক্ত করতে দেয়। খুব দরকারী.
ট্রায়হার্ডার

4
এটি দেখে আমি বুঝতে পারি না এটি কীভাবে আদৌ কার্যকর হবে। অভ্যন্তরীণ অবস্থাটি সর্বদা সত্য হবে না যেহেতু বাইরের টেবিলের যে কোনও সারিটি অভ্যন্তরীণ সারণীতেও পাওয়া যাবে এবং তাই প্রতিটি সারি সর্বদা কমপক্ষে নিজের সাথে মিলে যায়? আমি ক্যোয়ারীটি চেষ্টা করেছিলাম এবং আমার সন্দেহজনক ফলাফল পেয়েছে - প্রতিটি সারিই ফিরে আসে। তবে অনেকগুলি উদ্দীপনা নিয়ে আমি নিজেকে সন্দেহ করছি। অভ্যন্তরীণ কোয়েরিটি কি "AND mto.id <> mti.id" এর মতো কিছু মিস করছে না? এটি যুক্ত করার পরে এটি আমার পক্ষে কাজ করে।
ক্লক্স

2
@ কাসনোই ঠিক আছে। আমি এটি স্কুফিল্ডে রাখার চেষ্টা করেছি তবে স্কিমা তৈরি করা বাদ দিয়ে আমি যে সমস্ত ক্যোয়ারী চালানোর চেষ্টা করি তা ছেড়ে দিয়েছি। আমি বুঝতে পেরেছিলাম যে "" উপস্থিতি "সরিয়ে ফেলাও ক্যোয়ারীটি আমার পক্ষে সঠিকভাবে কাজ করে।
ক্লক্স

144

ডুপ্লিকেট সারিগুলির আইডি পাওয়ার জন্য লেভিকের জবাব বন্ধ করে দেওয়া GROUP_CONCATযদি আপনি এটি করতে পারেন যে আপনার সার্ভার সমর্থন করে (এটি আইডির একটি কমা দ্বারা পৃথকীত তালিকা ফিরিয়ে দেবে)।

SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUP BY name HAVING c > 1;

12
GROUP_CONCAT () সম্পর্কে না জেনে এই সমস্ত সময়! খুব খুব দরকারী।
aesede

ম্যাট সত্যিই প্রশংসা। এটি সত্যই সহায়ক! যারা phpmyadmin এ আপডেট করার চেষ্টা করছেন তাদের জন্য যদি আপনি এই জাতীয় ফাংশনটির সাথে আইডিটি একসাথে ছেড়ে যান: SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]এটি ইনলাইন সম্পাদনা সক্ষম করে এবং এতে জড়িত সমস্ত সারিগুলি আপডেট করা উচিত (বা কমপক্ষে প্রথমটির সাথে মিলিত হওয়া) তবে দুর্ভাগ্যক্রমে সম্পাদনাটি জাভাস্ক্রিপ্ট ত্রুটি তৈরি করেছে। ..
আর্মফুট

তারপরে আপনি কতগুলি আইডি সদৃশতার সাপেক্ষে গণনা করবেন?
সিএমসিডিগ্রাগনকাই

2
আমি কীভাবে সমস্ত আইডির গোষ্ঠীভুক্ত হব না, পরিবর্তে প্রথম থেকে শেষ পর্যন্ত তালিকাবদ্ধ; তাদের পাশের কলামগুলিতে সমস্ত স্ব স্ব মান সহ? সুতরাং এটির গোষ্ঠীকরণের পরিবর্তে এটি আইডি 1 এবং এর মান, আইডি 2 এবং এর মানটি দেখায়। আইডির মানগুলি একই হলে ইভেন।
মেলব্লেড

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

13

ধরে নিলে আপনার টেবিলটির নাম টেবিলএবিসি এবং আপনি যে কলামটি চান সেটি করল এবং টি 1 এর প্রাথমিক কীটি কী is

SELECT a.Key, b.Key, a.Col 
FROM TableABC a, TableABC b
WHERE a.Col = b.Col 
AND a.Key <> b.Key

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


4
+1 কারণ এটি সুবিধাজনক। যদিও, হাস্যকরভাবে, ফলাফলটি নিজেই নকলগুলি অন্তর্ভুক্ত করে (এটি a এবং b, তারপরে বি এবং এ তালিকাভুক্ত করে)
ফ্যাবিয়েন স্নোওয়ার্ট

2
@ ফ্যাবিএনসনওয়ার্ট আপনি এর চেয়ে কম (বা তার চেয়েও বেশি) তুলনা করে কিছু নকল থেকে মুক্তি পেতে পারেন
মাইকেল

@ টেকট্রাভেল টিঙ্ক আপনার উত্তরটি খুব স্পষ্ট, এর জন্য ধন্যবাদ তবে বৃহত টেবিলের জন্য এটি কিছুটা সময় নেয় (আরও 20'000 এন্ট্রি টেবিলের প্রায় 2 মিলিয়ন) এবং 25 টি প্রথম ফলাফল দেখানোর পরে, যদি আমি পরেরটি দেখানোর জন্য ক্লিক করি, তবে phpmyadmin শো ত্রুটি "# 1052 - কলামের আইডি 'ক্রম ধারাটি অস্পষ্ট "
বিসিএজি 2

12
SELECT * 
FROM `dps` 
WHERE pid IN (SELECT pid FROM `dps` GROUP BY pid HAVING COUNT(pid)>1)

1
না, কারণ এটি সম্ভবত লটের বেশ ধীরতম। Subselects হিসাবে তারা ফিরে প্রত্যেক সারিতে মৃত্যুদন্ড কার্যকর করছি, ধীর কুখ্যাতিপূর্ণভাবে হয়।
ওডম্যান

10

কর্মচারীর নাম কলামে কয়টি রেকর্ড নকল রয়েছে তা জানতে, নীচের ক্যোয়ারী সহায়ক;

Select name from employee group by name having count(*)>1;

9

সদৃশ থাকা সমস্ত ডেটা পেতে আমি এটি ব্যবহার করেছি:

SELECT * FROM TableName INNER JOIN(
  SELECT DupliactedData FROM TableName GROUP BY DupliactedData HAVING COUNT(DupliactedData) > 1 order by DupliactedData)
  temp ON TableName.DupliactedData = temp.DupliactedData;

টেবিল নাম = আপনি যে টেবিলটির সাথে কাজ করছেন তা।

DupliactedData = ডুপ্লিকেট করা ডেটা আপনি সন্ধান করছেন।


এটির প্রত্যেকটি নকলটিকে তার নিজস্ব সারিতে দেখায়। এটাই তো আমার দরকার. ধন্যবাদ।
উষ্ণস্বরে ডিস্কি

8

আমার চূড়ান্ত ক্যোয়ারী এখানে কয়েকটি উত্তর অন্তর্ভুক্ত করেছে যা সহায়তা করেছে - গোষ্ঠী, গণনা এবং GROUP_CONCAT দ্বারা একত্রিত।

SELECT GROUP_CONCAT(id), `magento_simple`, COUNT(*) c 
FROM product_variant 
GROUP BY `magento_simple` HAVING c > 1;

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

সারণী এবং কলামগুলি সেই অনুযায়ী পরিবর্তন করুন।


8

আমি কোনও JOIN পন্থা দেখছি না, যার সদৃশ শর্তে অনেক ব্যবহার রয়েছে।

এই পদ্ধতির আপনাকে প্রকৃত দ্বিগুণ ফলাফল দেয়।

SELECT t1.* FROM my_table as t1 
LEFT JOIN my_table as t2 
ON t1.name=t2.name and t1.id!=t2.id 
WHERE t2.id IS NOT NULL 
ORDER BY t1.name

2
এফওয়াইআই - আপনি 1 টির বেশি সদৃশ রেকর্ডের উপস্থিতির সম্ভাবনা থাকলে আপনি 'স্বতন্ত্র সামারকোল নির্বাচন করতে চান ...' না হলে ফলাফলগুলিতে নকল করা সারিগুলির সদৃশ থাকে contain
ড্রয়

7
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

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


7

টেকিং @ maxyfc এর উত্তর উপরন্তু, আমি খুঁজে প্রয়োজন সব সারি যে ডুপ্লিকেট মান সঙ্গে ফিরে হয়েছিল, তাই আমি তাদের মধ্যে সম্পাদনা করতে পারে মাইএসকিউএল Workbench :

SELECT * FROM table
   WHERE field IN (
     SELECT field FROM table GROUP BY field HAVING count(*) > 1
   ) ORDER BY field

6

আমি উপরের ফলাফলটি দেখেছি এবং কোয়েরিটি ভাল কাজ করবে যদি আপনার একক কলাম মান যা সদৃশ হয় তা পরীক্ষা করতে হবে। উদাহরণস্বরূপ ইমেল।

তবে যদি আপনাকে আরও কলামগুলি পরীক্ষা করে দেখতে হয় এবং ফলাফলের সংমিশ্রণটি পরীক্ষা করতে চান তবে এই ক্যোয়ারীটি ঠিকঠাক কাজ করবে:

SELECT COUNT(CONCAT(name,email)) AS tot,
       name,
       email
FROM users
GROUP BY CONCAT(name,email)
HAVING tot>1 (This query will SHOW the USER list which ARE greater THAN 1
              AND also COUNT)

ঠিক কী দরকার ছিল! এখানে আমার জিজ্ঞাসা, SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
নকলের

4

সদৃশগুলি সন্ধান করতে আমি উইন্ডোড ফাংশনগুলি (মাইএসকিউএল 8.0+) ব্যবহার করতে পছন্দ করি কারণ আমি পুরো সারিটি দেখতে পেতাম:

WITH cte AS (
  SELECT *
    ,COUNT(*) OVER(PARTITION BY col_name) AS num_of_duplicates_group
    ,ROW_NUMBER() OVER(PARTITION BY col_name ORDER BY col_name2) AS pos_in_group
  FROM table
)
SELECT *
FROM cte
WHERE num_of_duplicates_group > 1;

ডিবি ফিডল ডেমো


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

1
একই subquery দু'বার করা অকার্যকর বলে মনে হচ্ছে।
নোবেলপ্লিট

3

নীচে একাধিকবার ব্যবহৃত সমস্ত প্রোডাক্ট_আইডি খুঁজে পাবেন। আপনি প্রতিটি প্রোডাক্ট_আইডির জন্য কেবল একটি একক রেকর্ড পাবেন।

SELECT product_id FROM oc_product_reward GROUP BY product_id HAVING count( product_id ) >1

কোডটি নেওয়া হয়েছে: http : //ચેন্দরশানা.ব্লগস্পট.ইন.২০১৪ / ১২ / ফাইন্ড- ডুপ্লিকেট- রিকার্ডস-বেসড- অন-any.html


3
CREATE TABLE tbl_master
    (`id` int, `email` varchar(15));

INSERT INTO tbl_master
    (`id`, `email`) VALUES
    (1, 'test1@gmail.com'),
    (2, 'test2@gmail.com'),
    (3, 'test1@gmail.com'),
    (4, 'test2@gmail.com'),
    (5, 'test5@gmail.com');

QUERY : SELECT id, email FROM tbl_master
WHERE email IN (SELECT email FROM tbl_master GROUP BY email HAVING COUNT(id) > 1)

2
SELECT DISTINCT a.email FROM `users` a LEFT JOIN `users` b ON a.email = b.email WHERE a.id != b.id;

1
উল্লেখযোগ্য যে এটিকে অসহনীয়ভাবে ধীর করা হয় বা কলামটি অনুসন্ধান করা না থাকলে সূচিযুক্ত না করা সত্ত্বেও এটি শেষ নাও হতে পারে। অন্যথায়, আমি ডুপ্লিকেট সহ সারিগুলির সমস্ত আইডিতে পরিবর্তন a.emailকরতে a.*এবং পেতে সক্ষম হয়েছি ।
নোবেলপ্লিট

@ NobleUplift আপনি কি সম্পর্কে কথা বলছেন?
মাইকেল 18

@ মিশেল ওয়েল যেহেতু এটি তিন বছর বয়সী আমি মাইএসকিউএল এর যে কোনও সংস্করণ ব্যবহার করছিলাম তা পরীক্ষা করতে পারছি না, তবে আমি এই একই প্রশ্নটি এমন একটি ডাটাবেসে চেষ্টা করেছি যেখানে আমি নির্বাচিত কলামটিতে একটি সূচক নেই, তাই এটি বেশ খানিকটা সময় নিয়েছে কয়েক সেকেন্ড শেষ। SELECT DISTINCT a.*প্রায় তাত্ক্ষণিকভাবে সমাধানের জন্য এটি পরিবর্তন করা ।
NobleUplift

পুনঃটুইট আমি বুঝতে পারি এটি ধীর হয়ে উঠছে ... আমি যে অংশটি নিয়ে উদ্বিগ্ন তা হ'ল "শেষও হতে পারে না"।
মাইকেল 18

@ মিশেল আমার সিস্টেমে কোন টেবিলটি আমার চালু ছিল তা আমি মনে করি না, তবে কয়েক মিলিয়ন রেকর্ড প্রাপ্ত ব্যক্তিদের জন্য তারা সম্ভবত শেষ করতে পেরেছিল, তবে এমন সময় যা আমি এতক্ষণে ছেড়ে দিয়েছি যে কখন এটা আসলে শেষ হবে।
NobleUplift

1

একাধিক ক্ষেত্রের সাথে সদৃশ সারিগুলি অপসারণের জন্য, প্রথমে এগুলিকে নতুন স্বতন্ত্র কীতে ক্যানকেট করুন যা কেবলমাত্র পৃথক পৃথক সারিগুলির জন্য নির্দিষ্ট করা হয়েছে, তারপরে একই নতুন অনন্য কী দ্বারা সদৃশ সারিগুলি সরানোর জন্য "গ্রুপ বাই" কমান্ডটি ব্যবহার করুন:

Create TEMPORARY table tmp select concat(f1,f2) as cfs,t1.* from mytable as t1;
Create index x_tmp_cfs on tmp(cfs);
Create table unduptable select f1,f2,... from tmp group by cfs;

আপনি একটি ব্যাখ্যা যোগ করতে পারেন?
রবার্ট

কেন ব্যবহার CREATE TEMPORARY TABLE ...করবেন না ? আপনার সমাধানের একটি সামান্য ব্যাখ্যা দুর্দান্ত হবে।
ম্যাক্সবিবি

1

একটি খুব দেরিতে অবদান ... যদি এটি কাউকে লাইনটি থেকে নামাতে সহায়তা করে ... একটি ব্যাংকিং অ্যাপে আমার সাথে একটি মিলের মিলের লেনদেনের (আসলে অ্যাকাউন্টে অ্যাকাউন্টে স্থানান্তরের উভয় পক্ষের) সন্ধান করার জন্য কোন কাজ ছিল, কোনটি সনাক্ত করতে প্রতিটি আন্তঃ-অ্যাকাউন্ট-স্থানান্তর লেনদেনের জন্য 'থেকে' এবং 'থেকে' ছিল, সুতরাং আমরা এটি দিয়ে শেষ করেছি:

SELECT 
    LEAST(primaryid, secondaryid) AS transactionid1,
    GREATEST(primaryid, secondaryid) AS transactionid2
FROM (
    SELECT table1.transactionid AS primaryid, 
        table2.transactionid AS secondaryid
    FROM financial_transactions table1
    INNER JOIN financial_transactions table2 
    ON table1.accountid = table2.accountid
    AND table1.transactionid <> table2.transactionid 
    AND table1.transactiondate = table2.transactiondate
    AND table1.sourceref = table2.destinationref
    AND table1.amount = (0 - table2.amount)
) AS DuplicateResultsTable
GROUP BY transactionid1
ORDER BY transactionid1;

ফলাফলটি DuplicateResultsTableমিলেছে (যেমন ডুপ্লিকেট) লেনদেনগুলি সমেত সারি সরবরাহ করে তবে এটি একই জোড়ায় দ্বিতীয় বারের সাথে বিপরীতে একই লেনদেনের আইডি সরবরাহ করে, সুতরাং বাহ্যিকটি SELECTপ্রথম লেনদেন আইডি দ্বারা গোষ্ঠীতে আসে, যা সম্পন্ন হয় ব্যবহারের মাধ্যমে LEASTএবং GREATESTনিশ্চিত হয়ে যায় যে দুটি ট্রানজিডিশনের ফলাফলগুলিতে সর্বদা একই ক্রমে থাকে, যা এটি GROUPপ্রথমটি দ্বারা নিরাপদ করে তোলে , এইভাবে সমস্ত নকল ম্যাচগুলি বাদ দেয়। প্রায় এক মিলিয়ন রেকর্ডের মধ্য দিয়ে দৌড়ে এবং মাত্র 2 সেকেন্ডের নীচে 12,000+ ম্যাচ সনাক্ত করে। অবশ্যই লেনদেন হল প্রাথমিক সূচক, যা সত্যই সহায়তা করেছিল।




1

আপনি যদি সদৃশ ব্যবহার সরাতে চান DISTINCT

অন্যথায় এই কোয়েরিটি ব্যবহার করুন:

SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;


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