Υπάρχει τρόπος να κάνετε ένα ερώτημα Oracle
να συμπεριφέρεται σαν να περιέχει μια ρήτρα MySQL limit
;
Στην MySQL
, μπορώ να το κάνω αυτό:
select *
from sometable
order by name
limit 20,10
για να πάρω την 21η έως την 30η γραμμή (παραλείπω τις πρώτες 20, δίνω τις επόμενες 10). Οι σειρές επιλέγονται μετά την order by
, οπότε ξεκινάει πραγματικά από το 20ο όνομα αλφαβητικά.
Στο Oracle
, το μόνο πράγμα που αναφέρουν οι άνθρωποι είναι η ψευδοστήλη rownum
, αλλά αξιολογείται πριν από την order by
, πράγμα που σημαίνει το εξής:
select *
from sometable
where rownum <= 10
order by name
θα επιστρέψει ένα τυχαίο σύνολο δέκα σειρών ταξινομημένων με βάση το όνομα, κάτι που συνήθως δεν είναι αυτό που θέλω. Επίσης, δεν επιτρέπει τον προσδιορισμό μιας μετατόπισης.
Μπορείτε να χρησιμοποιήσετε ένα υποερώτημα για αυτό, όπως
select *
from
( select *
from emp
order by sal desc )
where ROWNUM <= 5;
Ρίξτε επίσης μια ματιά στο θέμα On ROWNUM and limiting results στο Oracle/AskTom για περισσότερες πληροφορίες.
Επικαιροποίηση: Για τον περιορισμό του αποτελέσματος τόσο με κατώτερα όσο και με ανώτερα όρια τα πράγματα γίνονται λίγο πιο φουσκωμένα με
select * from
( select a.*, ROWNUM rnum from
( <your_query_goes_here, with order by> ) a
where ROWNUM <= :MAX_ROW_TO_FETCH )
where rnum >= :MIN_ROW_TO_FETCH;
(Αντιγραφή από το συγκεκριμένο AskTom-άρθρο)
Ενημέρωση 2: Από την Oracle 12c (12.1) υπάρχει διαθέσιμη μια σύνταξη για τον περιορισμό των γραμμών ή την έναρξη σε μετατοπίσεις.
SELECT *
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
Ανατρέξτε στην αυτή την απάντηση για περισσότερα παραδείγματα. Ευχαριστούμε την Krumia για την υπόδειξη.
Μια αναλυτική λύση με ένα μόνο ένθετο ερώτημα:
SELECT * FROM
(
SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
)
WHERE MyRow BETWEEN 10 AND 20;
Η Rank()
θα μπορούσε να αντικαταστήσει την Row_Number()
αλλά μπορεί να επιστρέψει περισσότερες εγγραφές από όσες περιμένετε αν υπάρχουν διπλές τιμές για το όνομα.
(μη δοκιμασμένο) κάτι σαν αυτό μπορεί να κάνει τη δουλειά
WITH
base AS
(
select * -- get the table
from sometable
order by name -- in the desired order
),
twenty AS
(
select * -- get the first 30 rows
from base
where rownum < 30
order by name -- in the desired order
)
select * -- then get rows 21 .. 30
from twenty
where rownum > 20
order by name -- in the desired order
Υπάρχει επίσης η αναλυτική συνάρτηση rank, την οποία μπορείτε να χρησιμοποιήσετε για να διατάξετε κατά.