SQL: Einschränkung der Anzahl der zurückgegebenen Zeilen

Aus DBWiki
Wechseln zu: Navigation, Suche


Zurück zur Übersicht



Jeder SQL-Dialekt hat seine eigene Umsetzung, um die Anzahl der Datensätze in einer Abfrage einzuschränken. Die Standard-Lösung ist im Artikel Wie wählt man die n-te Zeile und n folgende Zeilen einer Tabelle aus? beschrieben. Da diese aber nicht immer einach zu implementieren ist, wird hier eine zweite Lösung für Access vorgestellt, die allerdings manchmal einen Zugriff durch VBA benötigt, um zuverlässige Resultate zu erzielen.


Bestimmte Bereiche von Datensätzen ausgeben

Lösung für Jet-SQL

Hinweis für Access-Anwender
Um die folgende Abfrage selbst testen zu können, müssen die Tabellen der Übungsdatenbank vorhanden sein.


Verwende folgenden Code in einem allgemeinen VBA-Modul:

Option Explicit
 
Private mRowNumCol As New Collection
 
'Falls ein Reset notwendig ist, diese Funktion vor dem Ausführen der Abfrage
'1x ausführen.
Public Function ResetRowNumber()
   Set mRowNumCol = New Collection
End Function
 
Public Function GetRowNumber(Key As String, _
                             Optional GroupKey As String) As Long
 
   Static grp As String
 
   On Error GoTo e
 
   If StrComp(grp, GroupKey, vbTextCompare) Then
      Set mRowNumCol = New Collection
      grp = GroupKey
   Else
      mRowNumCol.Add mRowNumCol.Count + 1, Key
   End If
 
   GetRowNumber = mRowNumCol(Key)
   Exit Function
 
e:
   Select Case Err
      Case 457: Resume Next
   End Select
End Function

In einer Abfrage kann die Funktion dann als 'Poor man's row_number()' eingesetzt werden. Um z. B. die Datensätze 3–5 und 9–11 anzuzeigen, kann wie folgt vorgegangen werden (ggf. vorher ResetRowNumber() ausführen):

SELECT GetRowNumber(CStr(ma_nr)) AS rn, ma_nr, ma_name
FROM   mitarbeiter
WHERE  GetRowNumber(CStr(ma_nr)) BETWEEN 3 AND 5 OR
       GetRowNumber(CStr(ma_nr)) BETWEEN 9 AND 11

Was dann zu dieser Ausgabe führt:

rn ma_nr ma_name
3 7902 Fuhrmann
4 7369 Schmidt
5 7698 Blank
9 7782 Kühne
10 7788 Scheidt
11 7844 Dreher

Lösung mittels Window Funktion row_number()

SELECT rn,
       ma_nr,
       ma_name
FROM   ( SELECT *,
         ROW_NUMBER() OVER () AS rn
         FROM mitarbeiter ) v
WHERE  rn BETWEEN 3 AND 5 OR
       rn BETWEEN 9 AND 11

Dieser DBFiddle zeigt das Ergebnis.

Erste x% Prozent der Datensätze ausgeben

Es sollen die ersten 75% der Datensätze absteigend sortiert nach Gehalt ausgegeben werden.

Lösung für Jet-Set

Hierfür kann das Jet-SQL Prädikat TOP x PERCENT. Der Wert für x muss dabei leider festkodiert verwendet werden.

Hinweis Zu beachten ist, dass hier 11 von 14 Datenätzen ausgegeben werden, was gerundet schon fast 79% von 14 Datensätzen ergibt. Für eine genaue Ausgabe empfiehlt es sich deshalb, die Anzahl aller Datensätze zu emitteln und das TOP-Prädikat mit einer fixen Zahl zu verwenden, die so z.B. Int(0.75 * 14) ermittelt werden kann und zum Ergebnis 10 führt.

SELECT TOP 75 PERCENT *
FROM   mitarbeiter
ORDER  BY gehalt DESC

Lösung mittels Window Funktion

SELECT ma_nr,
       ma_name,
       job,
       mgr,
       gehalt,
       provision,
       abt_nr
FROM   ( SELECT *,
                COUNT( * ) OVER ( ) AS cnt,
                ROW_NUMBER() OVER ( ORDER BY gehalt DESC ) AS rn
         FROM   mitarbeiter ) v
WHERE  100 * rn / cnt <= 75
ORDER  BY 5 DESC

Dieser DBFiddle zeigt das Ergebnis.



Zurück zur Übersicht