2010-08-17 22 views
17

मेरे पास ओरेकल डेटाबेस तालिका में पंक्तियां हैं जो दो फ़ील्ड के संयोजन के लिए अद्वितीय होनी चाहिए लेकिन तालिका पर अद्वितीय बाधा स्थापित नहीं की गई है, इसलिए मुझे उन सभी पंक्तियों को खोजने की ज़रूरत है जो स्वयं SQL का उपयोग करके बाधा का उल्लंघन करते हैं। दुर्भाग्य से मेरे कम एसक्यूएल कौशल कार्य तक नहीं हैं।एसक्यूएल: दो क्षेत्रों के आधार पर डुप्लीकेट कैसे ढूंढें?

मेरी तालिका में तीन कॉलम हैं जो प्रासंगिक हैं: entity_id, station_id, और obs_year। प्रत्येक पंक्ति के लिए station_id और obs_year का संयोजन अद्वितीय होना चाहिए, और मैं यह जानना चाहता हूं कि पंक्तियां हैं जो SQL क्वेरी के साथ उन्हें फ़्लश करके इसका उल्लंघन करती हैं।

मैं निम्नलिखित एसक्यूएल (this previous question ने सुझाव दिया) की कोशिश की है, लेकिन यह मेरे लिए काम नहीं करता है (मैं ORA-00918 स्तंभ अस्पष्ट परिभाषित मिल):

SELECT 
entity_id, station_id, obs_year 
FROM 
mytable t1 
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable 
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes 
ON 
t1.station_id = dupes.station_id AND 
t1.obs_year = dupes.obs_year 

कोई सुझाव दे सकते हैं मैं गलत क्या कर रही हूं , और/या इसे कैसे हल करें?

उत्तर

33
SELECT * 
FROM (
     SELECT t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn 
     FROM mytable t 
     ) 
WHERE rn > 1 
+0

का उपयोग करके इस प्रतिक्रिया के लिए बहुत कुछ धन्यवाद। दुर्भाग्यवश जब मैं इसे चलाता हूं तो मुझे "ओआरए -00 9 23: कीवर्ड से नहीं मिला जहां" अपेक्षित "संदेश मिलता है। –

+0

@ जेम्स: अब कोशिश करें – Quassnoi

+0

mssql में इसे काम करने के लिए FROM() paranthesis के पीछे 'x x' (नाम वास्तव में कोई फर्क नहीं पड़ता) डालना पड़ा था। बहुत बढ़िया जवाब! – Mafii

2

आपकी क्वेरी के फिर से लिखने

SELECT 
t1.entity_id, t1.station_id, t1.obs_year 
FROM 
mytable t1 
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable 
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes 
ON 
t1.station_id = dupes.station_id AND 
t1.obs_year = dupes.obs_year 

मुझे लगता है कि अस्पष्ट स्तंभ में त्रुटि (ORA-00918) था, क्योंकि आप select ing कॉलम जिनके नाम दोनों मेज और सबक्वेरी में छपी थी, लेकिन तुमने नहीं किया निर्दिष्ट करें कि आप इसे dupes से या mytable से (t1 के रूप में उपनाम) चाहते हैं।

1

क्या आप एक नई तालिका नहीं बना सकते जिसमें अद्वितीय बाधा शामिल हो, और फिर असफलताओं को अनदेखा करके, पंक्ति से डेटा पंक्ति में प्रतिलिपि बना सकते हैं?

+0

हाँ, यह एक अच्छा विचार है, धन्यवाद! बीटीडब्ल्यू मैं अपनी इकाई वर्ग में एनोटेशन का उपयोग करके अपनी तालिका पर बाधा उत्पन्न करने का तरीका जानने का प्रयास कर रहा हूं (मैं जेपीए/हाइबरनेट का उपयोग कर जावा डेवलपर हूं), http://stackoverflow.com/questions/3504477/ देखें कैसे-से-निर्दिष्ट-एक-संयोजन-कॉलम-होना-एक-अद्वितीय-बाधा- –

2

प्रारंभिक चयन में 3 फ़ील्ड्स बदलें होने की

SELECT 
t1.entity_id, t1.station_id, t1.obs_year 
10
SELECT entity_id, station_id, obs_year 
FROM mytable t1 
WHERE EXISTS (SELECT 1 from mytable t2 Where 
     t1.station_id = t2.station_id 
     AND t1.obs_year = t2.obs_year 
     AND t1.RowId <> t2.RowId) 
+0

ऐसा लगता है कि हम इसे एक दृश्य पर नहीं कर सकते: ओआरए -01445: कुंजी-संरक्षित तालिका – Thyag

1

आप मुख्य चयन में स्तंभों के लिए तालिका निर्दिष्ट करने के लिए की जरूरत है। साथ ही, मान लें कि entity_id mytable के लिए अनूठी कुंजी है और डुप्लीकेट खोजने के लिए अप्रासंगिक है, आपको डुप्लिकेट सबक्वायरी में इसे समूहित नहीं करना चाहिए।

प्रयास करें:

SELECT t1.entity_id, t1.station_id, t1.obs_year 
FROM mytable t1 
INNER JOIN (
SELECT station_id, obs_year FROM mytable 
GROUP BY station_id, obs_year HAVING COUNT(*) > 1) dupes 
ON 
t1.station_id = dupes.station_id AND 
t1.obs_year = dupes.obs_year 
+0

के बिना एक दृश्य दृश्य से ROWID का चयन नहीं कर सकता है, उदाहरण के लिए, मार्किंग सबक्वायरी में entity_id का उपयोग न करने के बारे में टिप के लिए , और उदाहरण के उदाहरण के लिए। –

0
SELECT * 
FROM (
     SELECT t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn 
     FROM mytable t 
     ) 
WHERE rn > 1 

Quassnoi द्वारा बड़े तालिकाओं के लिए सबसे कारगर है।

SELECT a.dist_code, a.book_date, a.book_no 
FROM trn_refil_book a 
WHERE EXISTS (SELECT 1 from trn_refil_book b Where 
     a.dist_code = b.dist_code and a.book_date = b.book_date and a.book_no = b.book_no 
     AND a.RowId <> b.RowId) 
     ; 

दिया 1322341

SELECT a.dist_code, a.book_date, a.book_no 
FROM trn_refil_book a 
INNER JOIN (
SELECT b.dist_code, b.book_date, b.book_no FROM trn_refil_book b 
GROUP BY b.dist_code, b.book_date, b.book_no HAVING COUNT(*) > 1) c 
ON 
a.dist_code = c.dist_code and a.book_date = c.book_date and a.book_no = c.book_no 
; 

की लागत की 1271699

जबकि

SELECT dist_code, book_date, book_no 
FROM (
     SELECT t.dist_code, t.book_date, t.book_no, ROW_NUMBER() OVER (PARTITION BY t.book_date, t.book_no 
      ORDER BY t.dist_code) AS rn 
     FROM trn_refil_book t 
     ) p 
WHERE p.rn > 1 
; 

1021984 की लागत दिया लागत दिया: मैं लागत के इस विश्लेषण के लिए किया था

तालिका अनुक्रमित नहीं किया गया था ....

+0

अपने उत्तर को सही तरीके से प्रारूपित करें। – SSP

0
SELECT entity_id, station_id, obs_year 
    FROM mytable 
GROUP BY entity_id, station_id, obs_year 
HAVING COUNT(*) > 1 

क्षेत्रों निर्दिष्ट दोनों का चयन करें और समूह द्वारा डुप्लीकेट ढूंढना।

यह निर्दिष्ट कॉलम के आधार पर किसी भी अन्य पंक्तियों से मेल खाने वाली किसी भी पंक्ति को खोजने के लिए GROUP BY का उपयोग करके काम करता है। HAVING COUNT(*) > 1 कहता है कि हम केवल 1 बार से अधिक होने वाली किसी भी पंक्ति को देखने में रुचि रखते हैं (और इसलिए डुप्लिकेट हैं)

+0

हाया, यह समस्या को हल कर सकता है ... लेकिन यह अच्छा होगा अगर आप थोड़ा और स्पष्टीकरण प्रदान कर सकते हैं कि यह कैसे और क्यों काम करता है :) भूलें - स्टैक ओवरफ़्लो पर नए शौकों के ढेर हैं, और वे अपनी विशेषज्ञता से एक या दो चीज़ सीखें - आपके लिए यह स्पष्ट नहीं है कि उनके लिए ऐसा क्यों न हो। –

+0

धन्यवाद टैरिन। यह किसी भी पंक्तियों को खोजने के लिए ग्रुप बाय का उपयोग करके काम करता है जो निर्दिष्ट कॉलम के आधार पर किसी अन्य पंक्ति से मेल खाते हैं। हैविंग COUNT (*)> 1 कहता है कि हम केवल 1 बार से अधिक होने वाली किसी भी पंक्ति को देखने में रुचि रखते हैं (और इसलिए डुप्लिकेट हैं) – grokster

+0

हाय, मुझे (टिप्पणियों में) न बताएं। मुझे एसक्यूएल पता है, मैं मुझसे नहीं पूछ रहा हूं ... इस तरह की स्पष्टीकरण "आपके पूर्ण उत्तर का हिस्सा" है ... इसलिए कृपया अपना उत्तर संपादित करें और इसे वहां जोड़ें। :) –

संबंधित मुद्दे