سؤال

لدي جدولين مع علاقة 1:n:"المحتوى" و"بيانات المحتوى التي تم إصدارها" (على سبيل المثال، كيان المقالة وجميع الإصدارات التي تم إنشاؤها من تلك المقالة).أرغب في إنشاء طريقة عرض تعرض الإصدار العلوي من كل "محتوى".

أستخدم حاليًا هذا الاستعلام (مع استعلام فرعي بسيط):

SELECT 
   t1.id, 
   t1.title, 
   t1.contenttext,
   t1.fk_idothertable
   t1.version
FROM mytable as t1
WHERE (version = (SELECT MAX(version) AS topversion
                  FROM mytable
                  WHERE (fk_idothertable = t1.fk_idothertable)))

الاستعلام الفرعي هو في الواقع استعلام لنفس الجدول الذي يستخرج الإصدار الأعلى من عنصر معين.لاحظ أن العناصر التي تم إصدارها سيكون لها نفس fk_idothertable.

في SQL Server حاولت إنشاء ملف عرض مفهرس من هذا الاستعلام ولكن يبدو أنني غير قادر على ذلك لأن الاستعلامات الفرعية غير مسموح بها وجهات النظر المفهرسة.لذا...هنا سؤالي...هل يمكنك التفكير في طريقة لتحويل هذا الاستعلام إلى نوع من الاستعلام باستخدام JOINs؟

يبدو أن طرق العرض المفهرسة لا يمكن أن تحتوي على:

  • الاستعلامات الفرعية
  • تعبيرات الجدول المشتركة
  • الجداول المشتقة
  • وجود بنود

أنا يائس.أي أفكار أخرى هي موضع ترحيب :-)

شكرًا جزيلاً!

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

المحلول

ربما لن يساعد هذا إذا كان الجدول قيد الإنتاج بالفعل ولكن الطريقة الصحيحة لتصميم ذلك هي جعل الإصدار = 0 هو الإصدار الدائم وزيادة إصدار المادة الأقدم دائمًا.لذا عندما تقوم بإدراج نسخة جديدة ستقول:

UPDATE thetable SET version = version + 1 WHERE id = :id
INSERT INTO thetable (id, version, title, ...) VALUES (:id, 0, :title, ...)

ثم سيكون هذا الاستعلام فقط

SELECT id, title, ... FROM thetable WHERE version = 0

لا توجد استعلامات فرعية، لا يوجد تجميع MAX.أنت تعرف دائمًا ما هو الإصدار الحالي.لن تضطر أبدًا إلى تحديد الحد الأقصى (الإصدار) لإدراج السجل الجديد.

نصائح أخرى

ربما شيء من هذا القبيل؟

SELECT
  t2.id,
  t2.title,
  t2.contenttext,
  t2.fk_idothertable,
  t2.version
FROM mytable t1, mytable t2
WHERE t1.fk_idothertable == t2.fk_idothertable
GROUP BY t2.fk_idothertable, t2.version
HAVING t2.version=MAX(t1.version)

مجرد تخمين جامح...

قد تتمكن من جعل MAX اسمًا مستعارًا للجدول يتم التجميع حسبه.

قد يبدو الأمر كالتالي:

SELECT 
   t1.id, 
   t1.title, 
   t1.contenttext,
   t1.fk_idothertable
   t1.version
FROM mytable as t1 JOIN
   (SELECT fk_idothertable, MAX(version) AS topversion
   FROM mytable
   GROUP BY fk_idothertable) as t2
ON t1.version = t2.topversion

أعتقد أن FerranB كان قريبًا ولكن لم يكن لديه التجميع الصحيح تمامًا:

with
latest_versions as (
   select 
      max(version) as latest_version,
      fk_idothertable
   from 
      mytable
   group by 
      fk_idothertable
)
select
  t1.id, 
  t1.title, 
  t1.contenttext,
  t1.fk_idothertable,
  t1.version
from 
   mytable as t1
   join latest_versions on (t1.version = latest_versions.latest_version 
      and t1.fk_idothertable = latest_versions.fk_idothertable);

م

If SQL Server accepts LIMIT clause, I think the following should work:
SELECT 
   t1.id, 
   t1.title, 
   t1.contenttext,
   t1.fk_idothertable
   t1.version
FROM mytable as t1 ordery by t1.version DESC LIMIT 1;
(DESC - For descending sort; LIMIT 1 chooses only the first row and
DBMS usually does good optimization on seeing LIMIT).

لا أعرف مدى فعالية هذا، ولكن:

SELECT t1.*, t2.version
FROM mytable AS t1
    JOIN (
        SElECT mytable.fk_idothertable, MAX(mytable.version) AS version
        FROM mytable
    ) t2 ON t1.fk_idothertable = t2.fk_idothertable

مثل هذا...أفترض أن "mytable" في الاستعلام الفرعي كان جدولًا فعليًا مختلفًا... لذا أسميته mytable2.إذا كان هو نفس الجدول، فسيظل هذا يعمل، ولكن بعد ذلك أتخيل أن fk_idothertable سيكون مجرد "id".


SELECT 
   t1.id, 
   t1.title, 
   t1.contenttext,
   t1.fk_idothertable
   t1.version
FROM mytable as t1
    INNER JOIN (SELECT MAX(Version) AS topversion,fk_idothertable FROM mytable2 GROUP BY fk_idothertable) t2
        ON t1.id = t2.fk_idothertable AND t1.version = t2.topversion

أتمنى أن يساعدك هذا

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