العلامات الهرمية في SQL
-
05-07-2019 - |
سؤال
لديّ تطبيق ويب PHP يستخدم قاعدة بيانات MySQL لعلامة الكائنات ، والتي استخدمت فيها بنية العلامة المقبولة كإجابة هذا السؤال جدا.
أرغب في تنفيذ التسلسل الهرمي للعلامة ، حيث يمكن أن يكون لكل علامة علامة أولياء فريدة. يبحث عن علامة الوالدين T تطابق مع جميع أحفاد T (أي T ، العلامات Whos هو T (أطفال T) ، أحفاد T ، إلخ).
يبدو أن أسهل طريقة للقيام بذلك هي إضافة حقل ParentId إلى جدول العلامات ، والذي يحتوي على معرف علامة الوالد الخاصة بالعلامة ، أو بعض الأرقام السحرية إذا لم يكن للعلامة الوالدين. ومع ذلك ، يتطلب البحث عن أحفاد عمليات البحث الكاملة المتكررة لقاعدة البيانات للعثور على العلامات في كل "جيل" ، والتي أود تجنبه.
طريقة (من المفترض) بشكل أسرع ، ولكن أقل تطبيعًا للقيام بذلك هي أن يكون لديك جدول يحتوي على جميع أطفال كل علامة ، أو حتى جميع نسل كل علامة. ومع ذلك ، فإن هذا يدير خطر البيانات غير المتسقة في قاعدة البيانات (مثل العلامة كونها الطفل لأكثر من والد واحد).
هل هناك طريقة جيدة لجعل الاستعلامات للعثور على أحفاد سريع ، مع الحفاظ على البيانات تطبيع قدر الإمكان؟
المحلول 2
إجابة علي لها رابط أشجار جو سيلكو والتسلسلات الهرمية في SQL لـ Smarties, ، مما يؤكد شكوكي - لا يوجد بنية قاعدة بيانات بسيطة توفر أفضل ما في العوالم. يبدو أن الأفضل لغرضي هو "شجرة الإدراج المتكررة" المفصلة في هذا الكتاب ، والتي تشبه "نموذج المجموعة المتداخلة" لرابط علي ، ولكن مع فهرسة غير متتالية. هذا يسمح بالإدراج (1) (لوس أنجلوس ترقيم الخط الأساسي غير المهيكلة) ، مع إعادة تنظيم الفهرس من حين لآخر وعند الحاجة.
نصائح أخرى
لقد قمت بتنفيذها باستخدام عمودين. أقوم بتبسيطها هنا قليلاً ، لأنني اضطررت إلى الاحتفاظ باسم العلامة في حقل/جدول منفصل لأنني اضطررت إلى توطينه بلغات مختلفة:
- بطاقة شعار
- طريق
انظر إلى هذه الصفوف على سبيل المثال:
tag path
--- ----
database database/
mysql database/mysql/
mysql4 database/mysql/mysql4/
mysql4-1 database/mysql/mysql4-1/
oracle database/oracle/
sqlserver database/sqlserver/
sqlserver2005 database/sqlserver/sqlserver2005/
sqlserver2005 database/sqlserver/sqlserver2008/
إلخ.
باستخدام like
المشغل على حقل المسار ، يمكنك بسهولة الحصول على جميع صفوف العلامات المطلوبة:
SELECT * FROM tags WHERE path LIKE 'database/%'
هناك بعض تفاصيل التنفيذ مثل عندما تنقل عقدة في التسلسل الهرمي ، يجب عليك تغيير جميع الأطفال أيضًا ، لكن هذا ليس صعبًا.
تأكد أيضًا من أن طول مسارك طويل بما فيه الكفاية - في حالتي ، لم أستخدم اسم العلامة للمسار ، ولكن حقل آخر للتأكد من أنني لا أحصل على مسارات طويلة جدًا.
يمكنك بناء ما تسميه كيمبال طاولة مساعد التسلسل الهرمي.
قل أنك التسلسل الهرمي يبدو مثل هذا: A -> B | ب -> ج | ج -> د
يمكنك إدراج السجلات في جدول يبدو هكذا
ParentID, ChildID, Depth, Highest Flag, Lowest Flag
A, A, 0, Y, N
A, B, 1, N, N
A, C, 2, N, N
A, D, 3, N, Y
B, B, 0, N, N
B, C, 1, N, N
B, D, 2, N, Y
C, C, 0, N, N
C, D, 1, N, Y
D, D, 0. N, Y
أعتقد أن لدي هذا صحيح .... على أي حال. النقطة المهمة هي أنك ما زلت تقوم بتخزين تسلسل هرمي بشكل صحيح ، فأنت تقوم فقط ببناء هذا الجدول من الجدول المناسب. استفسارات الجدول هذا مثل banshee. قل أنك تريد أن تعرف ما هو كل المستوى الأول أدناه B.
WHERE parentID = 'B' and Depth = 1
أود استخدام نوع من الصفيف لتخزين علامات الأطفال ، يجب أن يكون هذا أسرع بكثير من الانضمام إلى طاولة على نفسه (خاصة إذا كان لديك عدد كبير من العلامات). لقد ألقيت نظرة ، ولا يمكنني معرفة ما إذا كان MySQL لديه نوع بيانات صفيف أصلي ، ولكن يمكنك محاكاة ذلك باستخدام عمود نص وتخزين صفيف تسلسلي فيه. إذا كنت ترغب في تسريع الأمور بشكل أكبر ، فيجب أن تكون قادرًا على وضع فهرس بحث نص على هذا العمود لمعرفة العلامات المرتبطة.
تحرير] بعد قراءة مقالة علي ، فعلت المزيد من الصيد ووجدت هذه عرض تقديمي حول مجموعة من الأساليب لتنفيذ التسلسلات الهرمية في Postgres. قد لا تزال مفيدة لأغراض توضيحية.