سؤال

لديّ تطبيق ويب 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. قد لا تزال مفيدة لأغراض توضيحية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top