سؤال

لدي جدول مشابه لهذا:

CREATE TABLE example (
  id integer primary key,
  name char(200),
  parentid integer,
  value integer);

يمكنني استخدام حقل الأصل لترتيب البيانات في بنية شجرة.

الآن هذا هو الجزء الذي لا أستطيع حله.بالنظر إلى الأصل، هل من الممكن كتابة عبارة SQL لإضافة جميع حقول القيمة ضمن هذا الأصل والتكرار أسفل فرع الشجرة؟

تحديث: أنا أستخدم posgreSQL لذا فإن ميزات MS-SQL الرائعة غير متاحة لي.على أي حال، أود أن يتم التعامل مع هذا على أنه سؤال SQL عام.

راجع للشغل، أنا معجب جدًا بالحصول على 6 إجابات خلال 15 دقيقة من طرح السؤال!اذهب إلى تجاوز سعة المكدس!

هل كانت مفيدة؟

المحلول

هناك عدة طرق للقيام بما تحتاجه في PostgreSQL.

شيء من هذا القبيل:

create or replace function example_subtree (integer)
returns setof example as
'declare results record;
         child record;
 begin
  select into results * from example where parent_id = $1;
  if found then
    return next results;
    for child in select id from example
                  where parent_id = $1
      loop
        for temp in select * from example_subtree(child.id)
        loop
          return next temp;
        end loop;
      end loop;
  end if;
  return null;
end;' language 'plpgsql';

select sum(value) as value_sum
  from example_subtree(1234);

نصائح أخرى

فيما يلي مثال لبرنامج نصي يستخدم تعبير الجدول الشائع:

with recursive sumthis(id, val) as (
    select id, value
    from example
    where id = :selectedid
    union all
    select C.id, C.value
    from sumthis P
    inner join example C on P.id = C.parentid
)
select sum(val) from sumthis

يقوم البرنامج النصي أعلاه بإنشاء جدول "افتراضي" يسمى sumthis التي لديها أعمدة id و val.يتم تعريفه على أنه نتيجة اختيارين مدمجين معهما union all.

أولاً select يحصل على الجذر (where id = :selectedid).

ثانية select يتبع أبناء النتائج السابقة بشكل متكرر حتى لا يكون هناك شيء للعودة.

يمكن بعد ذلك معالجة النتيجة النهائية كجدول عادي.في هذه الحالة يتم جمع عمود val.

منذ الإصدار 8.4، أصبحت PostgreSQL تمتلك دعم الاستعلام العودي لتعبيرات الجدول الشائعة باستخدام معيار SQL WITH بناء الجملة.

إذا كنت تريد حلاً محمولاً يعمل على أي ANSI SQL-92 RDBMS، سوف تحتاج إلى إضافة عمود جديد إلى الجدول الخاص بك.

جو سيلكو هو المؤلف الأصلي للكتاب مجموعات متداخلة نهج لتخزين التسلسلات الهرمية في SQL.يمكنك جوجل التسلسل الهرمي "للمجموعات المتداخلة". لفهم المزيد عن الخلفية.

أو يمكنك فقط إعادة تسمية اسم الوالدين إلى com.leftid وإضافة أ com.rightid.

هذه هي محاولتي لتلخيص المجموعات المتداخلة، والتي ستكون قصيرة جدًا لأنني لست جو سيلكو:SQL هي لغة قائمة على المجموعة، ونموذج الجوار (تخزين معرف الأصل) ليس تمثيلًا قائمًا على المجموعة للتسلسل الهرمي.لذلك لا توجد طريقة قائمة على المجموعة للاستعلام عن مخطط الجوار.

لكن, ، فقد قدمت معظم المنصات الرئيسية امتدادات في السنوات الأخيرة للتعامل مع هذه المشكلة بالتحديد.لذا، إذا رد شخص ما بحل خاص بـ Postgres، فاستخدمه بكل الوسائل.

طريقة قياسية لإجراء استعلام متكرر في SQL هي العودية CTE. PostgreSQL يدعمهم منذ ذلك الحين 8.4.

في الإصدارات السابقة، يمكنك كتابة دالة عودية متكررة:

CREATE FUNCTION fn_hierarchy (parent INT)
RETURNS SETOF example
AS
$$
        SELECT  example
        FROM    example
        WHERE   id = $1
        UNION ALL
        SELECT  fn_hierarchy(id)
        FROM    example
        WHERE   parentid = $1
$$
LANGUAGE 'sql';

SELECT  *
FROM    fn_hierarchy(1)

انظر هذا المقال:

إذا كنت تستخدم SQL Server 2005، فهناك طريقة رائعة للقيام بذلك باستخدام تعبيرات الجدول الشائعة.

يتطلب الأمر كل الجهد المبذول عند إنشاء جدول مؤقت، ويسمح لك بشكل أساسي بالقيام بكل ذلك باستخدام "WTH" و"UNION" فقط.

هنا برنامج تعليمي جيد:

http://searchwindevelopment.techtarget.com/tip/0,289483,sid8_gci1278207,00.html

إستخدم تعبير الجدول المشترك.

قد ترغب في الإشارة إلى أن هذا هو SQL Server 2005 أو أعلى فقط. ديل راجان

وهنا مقال عند التكرار بواسطة SqlTeam بدون تعبيرات الجدول الشائعة.

يتم تجميع التعليمات البرمجية التالية واختبارها بشكل جيد.

create or replace function subtree (bigint)
returns setof example as $$
declare
    results record;
    entry   record;
    recs    record;
begin
    select into results * from example where parent = $1;
    if found then
        for entry in select child from example where parent = $1 and child  parent loop
            for recs in select * from subtree(entry.child) loop
                return next recs;
            end loop;
        end loop;
    end if;
    return next results;
end;
$$ language 'plpgsql';

الشرط "الطفل <> الوالد" مطلوب في حالتي لأن العقد تشير إلى نفسها.

استمتع :)

لدى Oracle "البدء بـ" و"الاتصال بواسطة"

select 
    lpad(' ',2*(level-1)) || to_char(child) s

from 
    test_connect_by 

start with parent is null
connect by prior child = parent;

http://www.adp-gmbh.ch/ora/sql/connect_by.html

على سبيل الإيجاز، على الرغم من أن السؤال قد تمت الإجابة عليه بشكل جيد للغاية، تجدر الإشارة إلى أنه إذا تعاملنا مع هذا على أنه:

سؤال SQL عام

فإن تطبيق SQL يكون مباشرًا إلى حد ما، حيث أن SQL'99 يسمح بالتكرار الخطي في المواصفات (على الرغم من أنني أعتقد أنه لا توجد أنظمة RDBMS تنفذ المعيار بالكامل) من خلال WITH RECURSIVE إفادة.لذلك من منظور نظري يمكننا القيام بذلك الآن.

لم يكن أي من الأمثلة مناسبًا بالنسبة لي، لذا قمت بإصلاحه على النحو التالي:

declare
    results record;
    entry   record;
    recs    record;
begin
    for results in select * from project where pid = $1 loop
        return next results;
        for recs in select * from project_subtree(results.id) loop
            return next recs;
        end loop;
    end loop;
    return;
end;

هل هذا خادم SQL؟ألا يمكنك كتابة إجراء مخزن في TSQL يتكرر ويجمع النتائج معًا؟

أنا مهتم أيضًا إذا كانت هناك طريقة SQL فقط للقيام بذلك.من الأجزاء التي أتذكرها من صف قواعد البيانات الجغرافية، يجب أن يكون هناك.

أعتقد أنه من الأسهل في SQL 2008 مع معرف التسلسل الهرمي

إذا كنت بحاجة إلى تخزين الرسوم البيانية التعسفية، وليس فقط التسلسلات الهرمية، فيمكنك دفع Postgres إلى الجانب وتجربة قاعدة بيانات الرسم البياني مثل أليجروغراف:

يتم تخزين كل شيء في قاعدة بيانات الرسم البياني كثلاثية (العقدة المصدر، الحافة، العقدة الهدف) ويمنحك دعمًا من الدرجة الأولى لمعالجة بنية الرسم البياني والاستعلام عنها باستخدام لغة تشبه لغة SQL.

إنه لا يتكامل بشكل جيد مع شيء مثل Hibernate أو Django ORM ولكن إذا كنت جادًا بشأن هياكل الرسم البياني (وليس فقط التسلسلات الهرمية مثل نموذج Nested Set) فتحقق من ذلك.

أعتقد أيضًا أن Oracle أضافت أخيرًا دعمًا للرسومات البيانية الحقيقية في أحدث منتجاتها، لكنني مندهش من أن الأمر استغرق وقتًا طويلاً، وقد تستفيد الكثير من المشكلات من هذا النموذج.

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