كيفية تحويل استعلام فرعي SQL إلى صلة
-
03-07-2019 - |
سؤال
لدي جدولين مع علاقة 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
أتمنى أن يساعدك هذا