PostgreSQL এ কীভাবে সদৃশ রেকর্ডগুলি পাওয়া যায়


189

আমার কাছে "ইউজার_লিঙ্কস" নামে একটি পোস্টগ্রিজ এসকিউএল ডাটাবেস টেবিল রয়েছে যা বর্তমানে নিম্নলিখিত সদৃশ ক্ষেত্রগুলিতে মঞ্জুরি দেয়:

year, user_id, sid, cid

অনন্য বাধ্যতা বর্তমানে প্রথম ক্ষেত্র "ID" নামক তবে আমি এখন নিশ্চিত করতে আমাদের কাছে বাধ্যতা যোগ করার জন্য দেখছি year, user_id, sidএবং cidপ্রত্যেকেই আলাদা কিন্তু আমি বাধ্যতা আবেদন করতে পারবেন না কারণ ডুপ্লিকেট মান ইতিমধ্যে বিদ্যমান যা এই বাধ্যতা লঙ্ঘন করে।

সব অনুলিপি খুঁজে পাওয়ার উপায় আছে?


উত্তর:


333

প্রাথমিক ধারণাটি গণনা সমষ্টি সহ একটি নেস্টেড ক্যোয়ারী ব্যবহার করবে:

select * from yourTable ou
where (select count(*) from yourTable inr
where inr.sid = ou.sid) > 1

আপনি অনুসন্ধান সংকীর্ণ করতে অভ্যন্তরীণ কোয়েরির যেখানে ধারাটি সামঞ্জস্য করতে পারেন।


মন্তব্যে উল্লিখিত এর জন্য আরও একটি ভাল সমাধান রয়েছে, (তবে সকলেই সেগুলি পড়েন না):

select Column1, Column2, count(*)
from yourTable
group by Column1, Column2
HAVING count(*) > 1

বা সংক্ষিপ্ত:

SELECT (yourTable.*)::text, count(*)
FROM yourTable
GROUP BY yourTable.*
HAVING count(*) > 1

65
আপনি select co1, col2, count(*) from tbl group by col1, col2 HAVING count(*)>1
HAVING

1
ধন্যবাদ @ এলেক্সকোভেলস্কি এর বক্তব্যটি আমার জন্য সংশোধন করা সহজ ছিল এবং দ্রুত চালিত হয়েছিল। উচ্চতর দৃশ্যমানতার জন্য আমি এর সাথে একটি উত্তর প্রস্তাব করব।
ভেসেন্টো

এই বিকল্পগুলি আমার কাজ করেছিল, অন্যরা ফলাফলগুলি গোষ্ঠীভুক্ত করে এবং এই বিকল্পগুলি আমাকে কেবল নথিভুক্ত রেকর্ডের পরিবর্তে সমস্ত সদৃশ রেকর্ড দিয়েছে, ধন্যবাদ!
rome3ro 18

1
আপনার এই উত্তরটি কিছুটা ধীর হতে হবে। একটি টেবিল 10k সারি * 18 কলামে,
ক্যোরিয়ায়

1
জ্যাম ঠিক আছে সেখানে ভাই। হ্যাঁ হ্যাঁ ধন্যবাদ। 💯
ডিপিএস

90

" PostgreSQL এর সাথে সদৃশ সারিগুলি সন্ধান করুন " থেকে এখানে স্মার্ট সমাধান রয়েছে:

select * from (
  SELECT id,
  ROW_NUMBER() OVER(PARTITION BY column1, column2 ORDER BY id asc) AS Row
  FROM tbl
) dups
where 
dups.Row > 1

11
এটি দ্রুত! সেকেন্ডের ভগ্নাংশে কয়েক মিলিয়ন সারিতে কাজ করেছেন। অন্যান্য উত্তর স্রেফ সেখানে ঝুলিয়ে
রেখেছিল

5
যত তাড়াতাড়ি আমি দেখতে পাচ্ছি, এই ক্যোয়ারী একটি গোষ্ঠীর মধ্যে সমস্ত সারি বিবেচনা করে না। এটা শুধুমাত্র কিছু সদৃশ শো, সদৃশ অংশ যদি আমি ভুল ROWNUM যোগ করা হয়েছে = 1. সঠিক আমার সাথে থাকবে
ভ্লাদিমির Filipchenko

9
@ ভ্লাদিমির ফিলিপচেনকো সব লাইনের সাথে রাখতে, আলেক্সকোভেলস্কি দ্রবণে একটি স্তর যুক্ত করুন:SELECT * FROM ( SELECT *, LEAD(row,1) OVER () AS nextrow FROM ( SELECT *, ROW_NUMBER() OVER(w) AS row FROM tbl WINDOW w AS (PARTITION BY col1, col2 ORDER BY col3) ) x ) y WHERE row > 1 OR nextrow > 1;
লে ড্রয়েড

3
@VladimirFilipchenko শুধু প্রতিস্থাপন ROW_NUMBER()সঙ্গে COUNT(*), এবং যোগ rows between unbounded preceding and unbounded followingপরORDER BY id asc
alexkovelsky

2
আমি খুঁজে পাওয়া অন্যান্য সমাধানের চেয়ে অনেক ভাল। সাথে dupes মুছে ফেলার জন্য ভাল সমানভাবে কাজ করে DELETE ...USINGএবং কিছু ছোটখাট সমন্বয়
ব্রান্ডন

6

আপনি ক্ষেত্রগুলিতে একই টেবিলটিতে যোগ দিতে পারেন যা নকল হবে এবং তারপরে আইডি ক্ষেত্রে অ্যান্টি-জয়েন করুন। প্রথম টেবিল ওরফে (tn1) থেকে আইডি ক্ষেত্রটি নির্বাচন করুন এবং তারপরে দ্বিতীয় টেবিলের ওরফে আইডি ফিল্ডে অ্যারে_অ্যাগ ফাংশনটি ব্যবহার করুন। অবশেষে, অ্যারে_এগজি ফাংশনটি সঠিকভাবে কাজ করার জন্য, আপনি ফলাফলগুলি tn1.id ক্ষেত্রের দ্বারা ভাগ করবেন। এটি এমন একটি ফলাফল সেট তৈরি করবে যাতে একটি রেকর্ডের আইডি এবং যোগদানের শর্তাবলী মাপসই সমস্ত আইডির একটি অ্যারে থাকে।

select tn1.id,
       array_agg(tn2.id) as duplicate_entries, 
from table_name tn1 join table_name tn2 on 
    tn1.year = tn2.year 
    and tn1.sid = tn2.sid 
    and tn1.user_id = tn2.user_id 
    and tn1.cid = tn2.cid
    and tn1.id <> tn2.id
group by tn1.id;

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

with dupe_set as (
select tn1.id,
       array_agg(tn2.id) as duplicate_entries, 
from table_name tn1 join table_name tn2 on 
    tn1.year = tn2.year 
    and tn1.sid = tn2.sid 
    and tn1.user_id = tn2.user_id 
    and tn1.cid = tn2.cid
    and tn1.id <> tn2.id
group by tn1.id
order by tn1.id asc)
select ds.id from dupe_set ds where not exists 
 (select de from unnest(ds.duplicate_entries) as de where de < ds.id)

সর্বাধিক সংখ্যক আইডির নকল রয়েছে তা বেছে নিন (আইডি ধরে নিচ্ছেন যে ইনপিকে পিকে বাড়ছে)। আপনার আইডিটি আপনার আশেপাশে রাখবে।


3

আরও সহজ করার জন্য আমি ধরে নিয়েছি যে আপনি কেবল কলাম বছরের জন্য একটি অনন্য বাধা প্রয়োগ করতে চান এবং প্রাথমিক কীটি আইডি নামের একটি কলাম।

আপনার চালিত হওয়া উচিত সদৃশ মানগুলি খুঁজতে,

SELECT year, COUNT(id)
FROM YOUR_TABLE
GROUP BY year
HAVING COUNT(id) > 1
ORDER BY COUNT(id);

উপরের স্কেল স্টেটমেন্টটি ব্যবহার করে আপনি একটি টেবিল পাবেন যাতে আপনার টেবিলের সমস্ত সদৃশ বছর রয়েছে। জন্য সর্বশেষ ডুপ্লিকেট এন্ট্রি ছাড়া সমস্ত সদৃশ মুছে ফেলতে আপনি SQL বিবৃতিতে উপরে ব্যবহার করা উচিত।

DELETE
FROM YOUR_TABLE A USING YOUR_TABLE_AGAIN B
WHERE A.year=B.year AND A.id<B.id;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.