سؤال

لدي مشكلة كبيرة مع بيان SQL في Oracle. أرغب في تحديد أفضل 10 سجلات تم طلبها بواسطة Storage_DB والتي ليست في قائمة من عبارة تحديد أخرى.

هذا واحد يعمل بشكل جيد لجميع السجلات:

SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
      STORAGE_GB IS NOT NULL AND 
        APP_ID NOT IN (SELECT APP_ID
                       FROM HISTORY
                        WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

لكن عندما أضيف

AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC

أحصل على نوع من السجلات "العشوائية". أعتقد أن الحد الأقصى يأخذ في وضعه قبل الطلب.

هل لدى شخص ما حل جيد؟ المشكلة الأخرى: هذا الاستعلام بطيء حقًا (سجلات 10K+)

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

المحلول

ستحتاج إلى وضع استعلامك الحالي في الاستعلام الفرعي على النحو التالي:

SELECT * FROM (
  SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
  ORDER BY STORAGE_GB DESC )
WHERE ROWNUM <= 10

ينطبق أوراكل رونوم إلى النتيجة بعد إرجاعها.
تحتاج إلى تصفية النتيجة بعد إرجاعها ، لذلك مطلوب مسمة فرعية. تستطيع ايضا استخذام مرتبة() وظيفة للحصول على نتائج Top-N.

للأداء حاول استخدام NOT EXISTS بدلاً من NOT IN. يرى هذه للمزيد من.

نصائح أخرى

إذا كنت تستخدم Oracle 12C ، استخدم:

جلبها التالي ن الصفوف فقط

SELECT DISTINCT 
  APP_ID, 
  NAME, 
  STORAGE_GB, 
  HISTORY_CREATED, 
  TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE  
  FROM HISTORY WHERE 
    STORAGE_GB IS NOT NULL AND 
      APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
  ORDER BY STORAGE_GB DESC
FETCH NEXT 10 ROWS ONLY

مزيد من المعلومات: http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html

فيما يتعلق بالأداء الضعيف ، هناك أي عدد من الأشياء التي يمكن أن يكون ، ويجب أن تكون حقًا سؤالًا منفصلًا. ومع ذلك ، هناك شيء واضح يمكن أن يكون مشكلة:

WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009') 

إذا كان History_Date حقًا عمودًا للتاريخ ، وإذا كان يحتوي على فهرس ، فسيتم عرض هذا إعادة الكتابة بشكل أفضل:

WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')  

وذلك لأن تحويل نوع البيانات يعطل استخدام فهرس B-Tree.

محاولة

SELECT * FROM users FETCH NEXT 10 ROWS ONLY;

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

 select * from 
     (select empno,
             ename,
             sal,
             row_number() over(order by sal desc nulls last) rnm
    from emp) 
 where rnm<=10
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top