आपको books
. के बीच N:M लिंक की आवश्यकता होगी और authors
, क्योंकि एक पुस्तक में कई लेखक हो सकते हैं और प्रत्येक लेखक ने एक से अधिक पुस्तकें लिखी हो सकती हैं। RDBMS में इसका मतलब है कि आपको written_by
. की आवश्यकता होगी टेबल।
books
. के बीच की कड़ी और publishers
हालांकि अलग है। किसी भी दी गई पुस्तक में केवल एक प्रकाशक हो सकता है (जब तक कि आपके सिस्टम में किसी पुस्तक के विभिन्न संस्करणों को एक ही पुस्तक नहीं माना जाता है)। तो आपको यहां एक publisher_id
की जरूरत है books
में विदेशी कुंजी
अंत में, और सबसे महत्वपूर्ण बात यह है कि आप पाठकों/उपयोगकर्ताओं को देख रहे हैं। और किताबों से उनका रिश्ता। स्वाभाविक रूप से, यह भी एक N:M संबंध है। मुझे यकीन है कि लोग एक से अधिक किताबें पढ़ेंगे (हम सभी जानते हैं कि क्या होता है यदि आप केवल एक ही पढ़ते हैं ...) और निश्चित रूप से एक से अधिक लोगों द्वारा एक किताब पढ़ी जाती है। इसके लिए book_users
. की आवश्यकता होती है कनेक्शन तालिका। यहां असली सवाल यह है कि इसे कैसे डिजाइन किया जाए। तीन बुनियादी डिज़ाइन हैं।
-
तालिकाओं को संबंध के प्रकार से अलग करें . (जैसा कि @just_somebody द्वारा उल्लिखित है) लाभ:आपके पास केवल INSERTS और DELETES हैं, कभी भी अपडेट नहीं होते हैं। हालांकि यह साफ-सुथरा दिखता है, और कुछ हद तक क्वेरी ऑप्टिमाइज़ेशन में मदद करता है, अधिकांश समय यह एक बड़े डेटाबेस चार्ट को दिखाने के अलावा कोई वास्तविक उद्देश्य नहीं देता है।
-
status
के साथ एक तालिका संकेतक . (जैसा कि @Hardcoded द्वारा बताया गया है) लाभ:आपके पास केवल एक टेबल है। नुकसान:आपके पास INSERTS, UPDATES और DELETES होंगे - कुछ RDBMS आसानी से संभाल सकता है, लेकिन जिसमें विभिन्न कारणों से इसकी खामियां हैं (उस पर बाद में) इसके अलावा, एक एकलstatus
फ़ील्ड का अर्थ है कि एक पाठक का किसी भी समय पुस्तक से केवल एक ही कनेक्शन हो सकता है, जिसका अर्थ है कि वह केवलplan_to_read
में हो सकता है ,is_reading
याhas_read
किसी भी समय स्थिति, और ऐसा होने पर यह एक आदेश मान लेता है। अगर वह व्यक्ति कभी भी इसे फिर से पढ़ने की योजना बना सकता है , या रोकें, फिर शुरुआत से फिर से पढ़ें आदि, स्थिति संकेतकों की इतनी सरल श्रृंखला आसानी से विफल हो सकती है, क्योंकि अचानक वह व्यक्तिis_reading
अभी, लेकिन साथ हीhas_read
बात। अधिकांश अनुप्रयोगों के लिए यह अभी भी एक उचित दृष्टिकोण है, और आमतौर पर स्थिति फ़ील्ड डिज़ाइन करने के तरीके होते हैं ताकि वे परस्पर अनन्य हों। -
एक लॉग . आप प्रत्येक स्थिति को तालिका में एक नई पंक्ति के रूप में सम्मिलित करते हैं - पुस्तक और पाठक का एक ही संयोजन एक से अधिक बार दिखाई देगा। आप
plan_to_read
. के साथ पहली पंक्ति INSERT करें , और एक टाइमस्टैम्प।is_reading
के साथ एक और . फिर एक औरhas_read
. के साथ . लाभ:आपको केवल पंक्तियों को सम्मिलित करना होगा, और आपको उन चीजों का एक साफ कालक्रम मिलता है जो हुआ। नुकसान:क्रॉस टेबल जॉइन को अब ऊपर के सरल तरीकों की तुलना में बहुत अधिक डेटा (और अधिक जटिल) से निपटना होगा।
आप अपने आप से पूछ सकते हैं कि किस परिदृश्य में आप INSERT, UPDATE या DELETE पर जोर क्यों दे रहे हैं? संक्षेप में, जब भी आप कोई UPDATE या DELETE कथन चलाते हैं, तो वास्तव में आपके खोने होने की बहुत संभावना होती है जानकारी। उस बिंदु पर आपको अपनी डिज़ाइन प्रक्रिया में रुकने और सोचने की ज़रूरत है "मैं यहाँ क्या खो रहा हूँ?" इस स्थिति में, आप घटनाओं का कालानुक्रमिक क्रम खो देते हैं। यदि उपयोगकर्ता अपनी पुस्तकों के साथ जो कर रहे हैं वह आपके आवेदन का केंद्र है, तो आप जितना हो सके उतना डेटा एकत्र करना चाहेंगे। भले ही यह अभी कोई मायने नहीं रखता, वह डेटा का प्रकार है जो आपको बाद में "जादू" करने की अनुमति दे सकता है। आप यह पता लगा सकते हैं कि कोई व्यक्ति कितनी तेजी से पढ़ रहा है, किसी पुस्तक को समाप्त करने के लिए उन्हें कितने प्रयासों की आवश्यकता है, आदि। वह सब उपयोगकर्ता से बिना किसी अतिरिक्त इनपुट के पूछे।
तो, मेरा अंतिम उत्तर वास्तव में एक प्रश्न है:
संपादित करें
चूंकि यह स्पष्ट नहीं हो सकता है कि लॉग कैसा दिखेगा, और यह कैसे कार्य करेगा, यहां ऐसी तालिका का एक उदाहरण दिया गया है:
CREATE TABLE users_reading_log (
user_id INT,
book_id INT,
status ENUM('plans_to_read', 'is_reading', 'has_read'),
ts TIMESTAMP DEFAULT NOW()
)
अब, अपने डिज़ाइन किए गए स्कीमा में "user_read" तालिका को अपडेट करने के बजाय जब भी किसी पुस्तक की स्थिति में परिवर्तन होता है तो आप लॉग में वही डेटा डालें जो अब जानकारी के कालक्रम से भर जाता है:
INSERT INTO users_reading_log SET
user_id=1,
book_id=1,
status='plans_to_read';
जब वह व्यक्ति वास्तव में पढ़ना शुरू करता है, तो आप एक और इंसर्ट करते हैं:
INSERT INTO users_reading_log SET
user_id=1,
book_id=1,
status='is_reading';
और इसी तरह। अब आपके पास "ईवेंट" का एक डेटाबेस है और चूंकि टाइमस्टैम्प कॉलम अपने आप भर जाता है, अब आप बता सकते हैं कि कब क्या हुआ। कृपया ध्यान दें कि यह प्रणाली यह सुनिश्चित नहीं करती है कि किसी विशिष्ट उपयोगकर्ता-पुस्तक जोड़ी के लिए केवल एक 'is_reading' मौजूद है। कोई पढ़ना बंद कर सकता है और बाद में जारी रख सकता है। आपके जॉइन को इसका हिसाब देना होगा।