MySQL में Join के साथ Delete करें


501

यहाँ मेरे टेबल बनाने के लिए स्क्रिप्ट है:

CREATE TABLE clients (
   client_i INT(11),
   PRIMARY KEY (client_id)
);
CREATE TABLE projects (
   project_id INT(11) UNSIGNED,
   client_id INT(11) UNSIGNED,
   PRIMARY KEY (project_id)
);
CREATE TABLE posts (
   post_id INT(11) UNSIGNED,
   project_id INT(11) UNSIGNED,
   PRIMARY KEY (post_id)
);

मेरे PHP कोड में, क्लाइंट को हटाते समय, मैं सभी प्रोजेक्ट पोस्ट हटाना चाहता हूं:

DELETE 
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id;

पोस्ट तालिका में client_idकेवल एक विदेशी कुंजी नहीं है project_id। मैं उन परियोजनाओं में पदों को हटाना चाहता हूं जो पास हो चुकी हैं client_id

यह अभी काम नहीं कर रहा है क्योंकि कोई भी पोस्ट हटाए नहीं गए हैं।


10
मुझे लगता है कि येहॉस्फ़ का उत्तर स्वीकार किया जाना चाहिए, क्योंकि वह जुड़ने का उपयोग करता है जैसा कि आपने पूछा था और यह एक इन-क्लॉज का उपयोग करने से बेहतर प्रदर्शन करता है जैसा कि yukondude प्रस्तावित ...
गेरार्डो

2
DELETE posts FROM posts JOIN projects ...एक IN (subquery)पैटर्न के बजाय पसंदीदा पैटर्न एक है। (येहॉस्फ़ का जवाब पसंदीदा पैटर्न का एक उदाहरण देता है।)
स्पेंसर from५

@GerardoGrignoli, यह एक विशेष इंजन या MySQL के संस्करण के लिए बेहतर प्रदर्शन करता है? एएफएआईके के समान होने के बाद से कोई भी कारण नहीं है कि दोनों प्रश्नों को अलग-अलग तरीके से किया जाए। बेशक, अगर मेरे पास हर समय के लिए एक निकल होता था, तो मेरी क्वेरी ऑप्टिमाइज़र ने कुछ बेवकूफी की ....
पॉल ड्रेपर

आप aliasतालिका के नाम के लिए भी उपयोग कर सकते हैं और इसका उपयोग कर सकते हैं।
बनिअम

जवाबों:


1253

आपको केवल यह निर्दिष्ट करने की आवश्यकता है कि आप प्रविष्टियों को postsतालिका से हटाना चाहते हैं :

DELETE posts
FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id

EDIT: अधिक जानकारी के लिए आप इस वैकल्पिक उत्तर को देख सकते हैं


117
यह ध्यान दिया जाना चाहिए कि यह सही उत्तर है क्योंकि ज्वाइन करने के लिए आपको "DELETE FROM posts" के बजाय "पोस्ट से पोस्ट" का उपयोग करने के लिए मजबूर करना पड़ता है, क्योंकि हटाने के लिए तालिका अब असंदिग्ध नहीं है। धन्यवाद!
सियानपोनलो

8
ध्यान दें कि आप यहां 'as' पद्धति का उपयोग नहीं कर सकते हैं। जैसे कि p.project_id पर p के रूप में इनर जॉइन प्रोजेक्ट्स ...
zzapper

14
वास्तव में आप शामिल तालिकाओं के लिए एक उपनाम का उपयोग कर सकते हैं, लेकिन मुख्य तालिका (पोस्ट) के लिए नहीं। "DELETE पदों से पोस्ट करता है INNER JOIN परियोजनाओं पर p.project_id = posts.project_id"
Weboide


14
यह सबसे अच्छा जवाब है, क्योंकि आप एक भी कार्रवाई में दोनों तालिकाओं से हटा सकते हैंDELETE posts , projects FROM posts INNER JOIN projects ON projects.project_id = posts.project_id WHERE projects.client_id = :client_id
Developerium

84

चूंकि आप कई तालिकाओं का चयन कर रहे हैं, इसलिए हटाने की तालिका अब असंदिग्ध नहीं है। आपको चयन करने की आवश्यकता है :

DELETE posts FROM posts
INNER JOIN projects ON projects.project_id = posts.project_id
WHERE projects.client_id = :client_id

इस मामले में, table_name1और table_name2एक ही तालिका है, इसलिए यह काम करेगा:

DELETE projects FROM posts INNER JOIN [...]

यदि आप चाहते हैं तो आप दोनों तालिकाओं से हटा भी सकते हैं:

DELETE posts, projects FROM posts INNER JOIN [...]

ध्यान दें कि order byऔर limit मल्टी-टेबल डिलीट के लिए काम न करें

यह भी जान लें कि यदि आप किसी तालिका के लिए उपनाम घोषित करते हैं, तो आपको तालिका का संदर्भ देते समय उपनाम का उपयोग करना होगा:

DELETE p FROM posts as p INNER JOIN [...]

Carpetsmoker और आदि से योगदान


3
यदि आप बेहतर उत्तर दे रहे हैं - तो कम से कम आप SQL को अधिक पठनीय बना सकते हैं। इस प्रश्न के अन्य सभी एसक्यूएल संदर्भों में बड़े अक्षरों में (0 वोटों के साथ एक को छोड़कर) कैपिटल है। मुझे यकीन नहीं है कि आपने मेरे संपादन क्यों बदले।
येहोसफ़

3
@ येशोसेफ, ऐसे लोगों का एक समूह है जो CAPS को वास्तव में भयावह पाते हैं। मेरा मानना ​​है कि मैं अकेला नहीं हूं, मैंने काफी लोगों को लोअरकेस स्टाइल भी देखा है।
पचेरियर

1
उचित रूप से - मैं उस शैली में अपना उत्तर लिखने के अपने अधिकार का सम्मान करता हूं; जो आप पसंद करते हैं;)
येहोसेफ़

7
कैप्स / नो कैप्स चर्चा में शामिल होने के लिए, सही है, आप अपनी पसंद के अनुसार शैली का उपयोग कर सकते हैं, लेकिन आपके उत्तर में, आप वास्तव में उन शैलियों का मिश्रण कर रहे हैं, जहाँ आप सुविधाजनक पाते हैं - ONपूंजीकृत है। कम-अनुभवी डेवलपर्स के लिए, यह बता सकता है कि स्टाइल के मामले में गन्दा और असंगत होना ठीक है।
शेड

16
CAPS कीवर्ड्स चमक नहीं रहे हैं। वे QUERIES बनाने योग्य हैं;)
Sachem

50

या एक ही बात, थोड़ा अलग (IMO मित्रता) वाक्यविन्यास के साथ:

DELETE FROM posts 
USING posts, projects 
WHERE projects.project_id = posts.project_id AND projects.client_id = :client_id;

BTW, mysql के साथ जुड़ने का उपयोग करते हुए लगभग हमेशा उपकेंद्रों की तुलना में तेज़ होता है ...


USING का क्या अर्थ है?
CMCDragonkai

1
की अच्छी व्याख्या USING: stackoverflow.com/questions/11366006/mysql-on-vs-use
bigtex777

10
@ bigtex777: कृपया ध्यान दें कि SELECT स्टेटमेंट्स में कीवर्ड का उपयोग DELETE स्टेटमेंट में एक ही कीवर्ड के साथ करने के लिए बहुत कम है। चयनों में यह स्तंभों की सूची को जोड़ने के लिए निर्दिष्ट करता है, जबकि DELETEs में यह सम्मिलित होने वाले सभी तालिकाओं की सूची है
ivanhoe

42

आप ALIAS का उपयोग इस तरह से भी कर सकते हैं कि यह मेरे डेटाबेस पर इसका उपयोग करता है! टी तालिका से हटाने की जरूरत है!

DELETE t FROM posts t
INNER JOIN projects p ON t.project_id = p.project_id
AND t.client_id = p.client_id

1
यह तालिका नामों को दोहराने से बचने के लिए मिश्रित कुंजी में उपयोगी है
मार्केज़

1
"वास्तव में आप शामिल तालिकाओं के लिए एक उपनाम का उपयोग कर सकते हैं, लेकिन मुख्य तालिका (पदों) के लिए नहीं। 'DELETE पदों में से कुछ शामिल हैं परियोजनाओं पर p.project_id = posts.project_id'" - @ Weboide
जेफ गिल्बर्ट

2
वास्तव में ( dev.mysql.com/doc/refman/5.0/en/delete.html से उद्धृत करते हुए ) "यदि आप किसी तालिका के लिए उपनाम घोषित करते हैं, तो आपको तालिका का संदर्भ देते हुए उपनाम का उपयोग करना होगा: DELETE t1। test2 कहाँ ... "तो एक उपनाम का उपयोग ठीक है।
पीटर बोवर्स

25

मैं इसके समाधान के लिए अधिक उपयोग में हूँ, लेकिन मैंने इसे MySQL में आज़माया नहीं है:

DELETE  FROM posts
WHERE   project_id IN (
            SELECT  project_id
            FROM    projects
            WHERE   client_id = :client_id
        );

85
आपको वास्तव में SQL में IN कीवर्ड का उपयोग करने से बचना चाहिए (भले ही यह आमतौर पर शुरुआती लोगों के लिए समझना आसान है) और इसके बजाय JOIN का उपयोग करें (जब संभव हो), क्योंकि उपश्रेणियों में आमतौर पर चीजें बहुत धीमी हो जाती हैं।
user276648 2

14
जब उप-क्वेरी द्वारा दी गई बड़ी संख्या में पंक्तियाँ होती हैं, तो DB को क्रैश करना पड़ता है। यह बेहद धीमा भी है।
राज

2
@yukondude वास्तव में "IN" 1 पर "JOIN" की तुलना में समझने में बहुत आसान है, और यही कारण है कि जो लोग SQL से वास्तव में परिचित नहीं हैं वे हर जगह "IN" लिखेंगे, जबकि वे "JOIN" का उपयोग कर सकते हैं जो बेहतर प्रदर्शन करता है ( या जो क्वेरी के आधार पर बहुत बेहतर है)। मुझे याद है कि कई साल पहले, मेरे सभी एसक्यूएल प्रश्नों को किसी ऐसे व्यक्ति द्वारा फिर से लिखा जाएगा जो वास्तव में अच्छे प्रश्नों को लिखना जानता था। इसलिए मैंने "IN" से बचने के लिए टिप्पणी को जोड़ा, ताकि लोगों को पता चले कि यदि संभव हो, तो उन्हें इसका उपयोग करने से बचना चाहिए।
user276648

10
इस पृष्ठ पर आने का बहुत कारण यह है कि मैंने एक IN स्टेटमेंट के साथ जो क्वेरी लिखी थी वह कुत्ते की धीमी थी। निश्चित रूप से यहां स्वीकृत उत्तर से बचें।
माइकल्स

4
यह प्रश्न जितना पुराना है, यह जानना महत्वपूर्ण है कि आपको IN के बजाय JOIN का उपयोग क्यों करना चाहिए। जब वह स्थिति किसी पंक्ति पर चलती है, तो वह उस क्वेरी को IN के अंदर चलाने वाली है। इसका मतलब है, अगर 100 पंक्तियाँ हैं, जिन्हें उस के खिलाफ जाँचने की आवश्यकता है, तो उस उपश्रेणी को 100 बार चलाया जा सकता है। जबकि एक JOIN केवल ONCE चलेगा। इसलिए, जैसे-जैसे आपका db बड़ा और बड़ा होता जाता है, उस क्वेरी को खत्म होने में अधिक समय और अधिक समय लगने वाला है। @ मार्कस सिर्फ इसलिए कि कुछ महत्वपूर्ण नहीं है इसका मतलब यह नहीं है कि आपको खराब कोड लिखना चाहिए। इसे थोड़ा बेहतर लिखना भविष्य में आपके बहुत समय और सिरदर्द से बचाएगा। :)
राइजिंगसुन

11

JOIN के साथ MySQL DELETE रिकॉर्ड

आप आमतौर पर INNER JOIN को सेलेक्ट स्टेटमेंट में उस टेबल से रिकॉर्ड का चयन करने के लिए उपयोग करते हैं जिसमें अन्य टेबल में संबंधित रिकॉर्ड होते हैं। हम किसी तालिका से रिकॉर्ड हटाने के लिए DELETE स्टेटमेंट के साथ INNER JOIN क्लॉज का भी उपयोग कर सकते हैं और अन्य तालिकाओं में इसी रिकॉर्ड जैसे, T1 और T2 दोनों टेबल से रिकॉर्ड को हटाने के लिए जो किसी विशेष स्थिति को पूरा करते हैं, आप निम्न कथन का उपयोग करते हैं:

DELETE T1, T2
FROM T1
INNER JOIN T2 ON T1.key = T2.key
WHERE condition

ध्यान दें कि आपने DELETE और FROM के बीच T1 और T2 नाम रखे हैं। यदि आप T1 तालिका को छोड़ते हैं, तो DELETE कथन केवल T2 तालिका में रिकॉर्ड हटाता है, और यदि आप T2 तालिका को छोड़ते हैं, तो T1 तालिका में केवल रिकॉर्ड हटा दिए जाते हैं।

T1.key = T2.key में शामिल होने की शर्त T2 तालिका में संबंधित रिकॉर्ड को निर्दिष्ट करती है जिसे हटाने की आवश्यकता है।

WHERE क्लॉज में स्थिति निर्दिष्ट करती है कि T1 और T2 में कौन से रिकॉर्ड डिलीट करने की जरूरत है।


11

एकल तालिका हटाएं:

postsतालिका से प्रविष्टियों को हटाने के लिए :

DELETE ps 
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id;

projectsतालिका से प्रविष्टियों को हटाने के लिए :

DELETE pj 
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id;

clientsतालिका से प्रविष्टियों को हटाने के लिए :

DELETE C
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id;

एकाधिक तालिकाएँ हटाएं:

शामिल किए गए परिणामों में से कई तालिकाओं से प्रविष्टियों को हटाने के लिए आपको तालिका के नाम निर्दिष्ट करने की आवश्यकता है DELETE कॉमा से अलग सूची के :

मान लीजिए आप सभी तीन तालिकाओं (से प्रविष्टियां हटाना चाहते हैं posts, projects, clients) एक विशेष ग्राहक के लिए:

DELETE C,pj,ps 
FROM clients C 
INNER JOIN projects pj ON C.client_id = pj.client_id
INNER JOIN posts ps ON pj.project_id = ps.project_id
WHERE C.client_id = :client_id


4

एक उप-चयन का उपयोग करके हटाने का एक अन्य तरीका जो उपयोग करने से बेहतर है INवह होगाWHERE EXISTS

DELETE  FROM posts
WHERE   EXISTS ( SELECT  1 
                 FROM    projects
                 WHERE   projects.client_id = posts.client_id);

बजाय में शामिल होने के इस उपयोग करने के लिए एक कारण यह है एक है कि DELETEके साथ JOINमना करता है के उपयोग LIMIT। यदि आप ब्लॉक में डिलीट करना चाहते हैं तो फुल टेबल लॉक का उत्पादन न करें, तो आप LIMITइस DELETE WHERE EXISTSविधि का उपयोग कर सकते हैं ।


1
क्या यह क्वेरी "उपनाम" के साथ लिखी जा सकती है? यह सिंटैक्स से बहुत स्पष्ट नहीं है कि कैसे postsEXISTS () एक ही है postsकि पंक्तियों को हटा दिया गया है। (IMHO वैसे भी)
मैटबियनको

मैं आपको सुनता हूं, लेकिन एलियास को तालिका से हटाने की अनुमति नहीं है। उप क्वेरी में "पोस्ट" को पूर्ण तालिका नाम होना चाहिए, जिसका अर्थ है कि यदि आप उस तालिका को अपने उप-चयन से फिर से उपयोग करना चाहते हैं, तो आपको इसे वहां उपनाम देना होगा।
जिम क्लॉस

1
यह काम करता है:DELETE p FROM posts p WHERE EXISTS ( SELECT 1 FROM projects WHERE projects.client_id = p.client_id);
MattBianco

4
mysql> INSERT INTO tb1 VALUES(1,1),(2,2),(3,3),(6,60),(7,70),(8,80);

mysql> INSERT INTO tb2 VALUES(1,1),(2,2),(3,3),(4,40),(5,50),(9,90);

एक तालिका से DELETE रिकॉर्ड:

mysql> DELETE tb1 FROM tb1,tb2 WHERE tb1.id= tb2.id;

दोनों तालिकाओं से प्राप्त करें:

mysql> DELETE tb2,tb1 FROM tb2 JOIN tb1 USING(id);

1

यदि जुड़ना आपके लिए काम नहीं करता है तो आप इस समाधान की कोशिश कर सकते हैं। यह विदेशी कुंजी + विशिष्ट जहां स्थिति का उपयोग नहीं करते हुए टी 1 से अनाथ रिकॉर्ड को हटाने के लिए है। यानी यह तालिका 1 से रिकॉर्ड हटाता है, जिसमें खाली फ़ील्ड "कोड" है और जो तालिका 2 में रिकॉर्ड नहीं है, जो फ़ील्ड "नाम" से मेल खाता है।

delete table1 from table1 t1 
    where  t1.code = '' 
    and 0=(select count(t2.name) from table2 t2 where t2.name=t1.name);


-3

- ध्यान दें कि आप मेज पर एक उपनाम का उपयोग नहीं कर सकते हैं जहां आपको हटाने की आवश्यकता है

DELETE tbl_pagos_activos_usuario
FROM tbl_pagos_activos_usuario, tbl_usuarios b, tbl_facturas c
Where tbl_pagos_activos_usuario.usuario=b.cedula
and tbl_pagos_activos_usuario.cod=c.cod
and tbl_pagos_activos_usuario.rif=c.identificador
and tbl_pagos_activos_usuario.usuario=c.pay_for
and tbl_pagos_activos_usuario.nconfppto=c.nconfppto
and NOT ISNULL(tbl_pagos_activos_usuario.nconfppto)
and c.estatus=50
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.