DB2 için LIMIT eşdeğeri


94

LIMITİSeries için DB2'de nasıl iş yaparsınız ?

50.000'den fazla kaydı olan bir tablom var ve 0 ile 10.000 arası kayıtları döndürmek ve 10.000 ile 20.000 arasında kayıtları döndürmek istiyorum.

SQL'de LIMIT 0,10000sorgunun sonunda 0 ila 10.000 LIMIT 10000,10000arasında ve sorgunun sonunda 10000 ila 20.000 arasında yazdığınızı biliyorum

Peki, bu DB2'de nasıl yapılır? Kod ve sözdizimi nedir? (tam sorgu örneği takdir edilmektedir)


ROW_NUMBER () yalnızca iSeries DB2 V5R4'te uygulandı. Önceki sürümler için benzer olan RRN () kullanmayı deneyin.
Paul Morgan

RRN (), row_number () 'dan tamamen farklıdır.
Brandon Peterson

benim için çalışmadı. Sytanx hatası.
elcool

1
Satırın fiziksel göreceli kayıt numarasını verecek olan RRN'yi (dosya adı) deneyin. RRN sıralı olmayacak ve satırlar silinmişse sayıları atlayabilir. RRN ayrıca anahtara göre sıralı olmayacak, ancak silme gerçekleşmediyse toplamaya göre sıralı olacaktır. Her durumda RRN, bir satır için benzersiz olacaktır ve tablonun alt kümelerini seçmek için kullanılabilir.
Paul Morgan

Yanıtlar:


143

Kullanarak FETCH FIRST [n] ROWS ONLY:

http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.perf/db2z_fetchfirstnrows.htm

SELECT LASTNAME, FIRSTNAME, EMPNO, SALARY
  FROM EMP
  ORDER BY SALARY DESC
  FETCH FIRST 20 ROWS ONLY;

Aralıkları elde etmek için ROW_NUMBER()(v5r4'ten beri) kullanmanız ve bunu şu WHEREmadde dahilinde kullanmanız gerekir : (buradan çalındı: http://www.justskins.com/forums/db2-select-how-to-123209.html )

SELECT code, name, address
FROM ( 
  SELECT row_number() OVER ( ORDER BY code ) AS rid, code, name, address
  FROM contacts
  WHERE name LIKE '%Bob%' 
  ) AS t
WHERE t.rid BETWEEN 20 AND 25;

evet, bunu da buldum hehe. Aynı zamanda soruyu, orta sıraları da istediğimi belirtmek için düzenliyordum.
elcool

2
ROW_NUMBER ile buna benzer bir şey yapmanız gerekiyor: justskins.com/forums/db2-select-how-to-123209.html
Joe

ROW_NUMBERgeçerli bir anahtar kelime değil. Ama bağlantı için teşekkürler, bana bir fikir verdi ve işe yarıyor.
elcool

13

Bu yöntemi geliştirdi:

Benzersiz bir değere sahip bir masaya İHTİYACINIZ VAR.

10.000 - 25.000 arası satırlar istiyorsanız ve Tablonuzda 40.000 satır varsa, önce başlangıç ​​noktasını ve toplam satırları almanız gerekir:

int start = 40000 - 10000;

int total = 25000 - 10000;

Ve sonra bunları kodla sorguya iletin:

SELECT * FROM 
(SELECT * FROM schema.mytable 
ORDER BY userId DESC fetch first {start} rows only ) AS mini 
ORDER BY mini.userId ASC fetch first {total} rows only

10000. satırın sonuç kümesinden çıkarıldığını, ilk satırın 10001. satır olduğunu unutmayın.
mavimsi

1
İlginç çözüm. Bunu H2 test veritabanı ile uyumluluk için kullanacaktım ... Ama ne yazık ki, SELECT row_number () OVER (ORDER BY code) yaklaşımından ~ 30 kat daha yavaş çalışıyor.
manuna

9

OFFSET ve LIMIT desteği yakın zamanda i 7.1 ve 7.2 için DB2'ye eklendi. Bu desteği almak için aşağıdaki DB PTF grup seviyelerine ihtiyacınız vardır:

  • IBM i 7.2 için SF99702 seviye 9
  • IBM i 7.1 için SF99701 seviye 38

Daha fazla bilgi için buraya bakın: OFFSET ve LIMIT belgeleri , DB2 for i Enhancement Wiki


7

İşte bulduğum çözüm:

select FIELD from TABLE where FIELD > LASTVAL order by FIELD fetch first N rows only;

LASTVAL'i 0'a (veya bir metin alanı için '') başlatıp, ardından bunu en son kayıt kümesindeki son değere ayarlayarak, bu, N kayıt yığınları halinde tablo boyunca ilerleyecektir.


(Başlangıçta değeri tabloya koyduğunuzu düşünmüştüm, bu eşzamanlı bir sistemde olağanüstü derecede sorunlu olurdu ) Evet, bu, tablo boyunca sıralı bir okuma yaptığınız durumlarda işe yaramalı, ancak bir tür Sütundaki Naynı değerlerin sayısından daha küçük olması durumunda bağ-kırıcı sütun (bu da kullanıldığında doğrudur ROW_NUMBER()) Başlangıç ​​değerleri de dikkatle seçilmelidir - 0eğer sütun negatif bir değer içeriyorsa açıkça sorunlu olacaktır . Boş değerlerle bakıma ihtiyaç duyulacaktır. Sayfalar atlanırsa çalışmaz.
Clockwork-Muse

Yorum için teşekkürler. Sorguyu kontrol etmek için kullandığımız alanın benzersiz ve monoton bir şekilde arttığına dair örtük bir varsayım olduğunu düşünüyorum. Bu varsayımlar geçerli olmazsa, tablodaki tüm kayıtları ziyaret etmek için işe yaramayacağını kabul ediyorum. Ve tabii ki, mantıklı bir LASTVAL ile başlamanız gerektiği konusunda haklısınız. Genel olarak, "TABLO'dan MİNİMUM (ALAN) seçin" tarafından döndürülen şeyle başlamak isteyeceğinizi düşünüyorum. Alan dizine alınmışsa, çoğu db motoru tüm tabloyu sırayla okumaktan daha iyi sonuç verecektir.
Tom Barron

2

@ elcool'un çözümü akıllıca bir fikirdir, ancak toplam satır sayısını bilmeniz gerekir (bu, sorguyu yürütürken bile değişebilir!). Bu yüzden, maalesef 2 yerine 3 alt sorgu gerektiren değiştirilmiş bir sürüm öneriyorum:

select * from (
    select * from (
        select * from MYLIB.MYTABLE
        order by MYID asc 
        fetch first {last} rows only 
        ) I 
    order by MYID desc
    fetch first {length} rows only
    ) II
order by MYID asc

nerede {last}ihtiyacım olan son kaydın satır numarası {length}ile değiştirilmeli ve ihtiyacım olan satır sayısı olarak hesaplanarak değiştirilmelidir last row - first row + 1.

Örneğin, 10'dan 25'e kadar olan satırlar istersem (toplam 16 satır), {last}25 olur ve {length}25-10 + 1 = 16 olur.


Başka bir kişinin sorularını yanıtlamak için zaman ayırdığında olumsuz oy kullananlardan nefret ediyorum.
jp2code

1

OPTIMIZE FOR n ROWS yan tümcesini de dikkate almalısınız. Tüm bunlarla ilgili daha fazla ayrıntı, SELECT deyimlerini kısıtlama yönergeleri başlığındaki DB2 LUW belgelerinde :

  • OPTIMIZE FOR yan tümcesi, sonucun yalnızca bir alt kümesini alma veya yalnızca ilk birkaç satırı almaya öncelik verme niyetini bildirir. İyileştirici daha sonra ilk birkaç satırı almak için yanıt süresini en aza indiren erişim planlarını seçebilir.

1

Bunu dene

SELECT * FROM
    (
        SELECT T.*, ROW_NUMBER() OVER() R FROM TABLE T
    )
    WHERE R BETWEEN 10000 AND 20000

0

Bir DB2 tablosunda verimli bir şekilde sayfalandırmanın 2 çözümü vardır:

1 - row_number () fonksiyonunu ve başka bir gönderide sunulan OVER cümlesini kullanan teknik ("SELECT row_number () OVER (ORDER BY ...)"). Bazı büyük masalarda performansların bazen düştüğünü fark ettim.

2 - kaydırılabilir bir imleç kullanan teknik. Uygulama, kullanılan dile bağlıdır. Bu teknik büyük masalarda daha sağlam görünüyor.

Önümüzdeki yıl bir seminerde PHP'de uygulanan 2 tekniği sundum. Slayt şu bağlantıda mevcuttur: http://gregphplab.com/serendipity/uploads/slides/DB2_PHP_Best_practices.pdf

Maalesef bu belge sadece Fransızca.


0

Şu mevcut seçenekler var: -

DB2 has several strategies to cope with this problem.
You can use the "scrollable cursor" in feature.
In this case you can open a cursor and, instead of re-issuing a query you can FETCH forward and backward.
This works great if your application can hold state since it doesn't require DB2 to rerun the query every time.
You can use the ROW_NUMBER() OLAP function to number rows and then return the subset you want.
This is ANSI SQL 
You can use the ROWNUM pseudo columns which does the same as ROW_NUMBER() but is suitable if you have Oracle skills.
You can use LIMIT and OFFSET if you are more leaning to a mySQL or PostgreSQL dialect.  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.