![]() |
SQL: benachbarte Datensätze mitselektieren
Folgendes Problem.
Meine Datensätze werden geordnet. Für einen bestimmten Datensatz ist der Primary-Key bekannt. Aus der Tabelle möchte ich dieses Element inklusive der 2 nächstkleineren Elemente und der 2 nächstgrößeren Elemente als Ergebnismenge verarbeiten. Hat Jemand eine Idee wie ich das mit weniger als 3 Queries schaffen kann? |
Re: SQL: Nachbarn eines Datensatzes mitselektien
Moin,
es ist eigentlich simpel: nehmen wir an, du sortierst nach dem Feld id. Dir ist die ID des eigentlichen Datensatzes bekannt, d.h. du selektierst erstmal das Objekt:
SQL-Code:
Anschliessend selektierst du die naechsten 2 Datensaetze:
SELECT * FROM foo WHERE id = %id
SQL-Code:
Und zu guter Letzt noch die vorherigen beiden:
SELECT * FROM foo WHERE id > %id ORDER BY id ASC LIMIT 2
SQL-Code:
So, das waren jetzt drei. Wir koennen die ersten beiden Queries aber verbinden:
SELECT * FROM foo WHERE id < %id ORDER BY id DESC LIMIT 2
SQL-Code:
Nun weisst du dass die erste Row des Ergebnis-Sets der eigentliche Datensatz ist und alles was nachher kommt sind die naechsten Datensaetze, und hast das Ganze in 2 Queries. Auf ein Query runterzukommen geht eigentlich nur mit Hilfe von UNION:
SELECT * FROM foo WHERE id >= %id ORDER BY id ASC LIMIT 3
SQL-Code:
Hab ich grad nicht getestet, muesste aber funktionieren. Das Ding ist allerdings ein Trugschluss, da der DB-Server intern sowieso 2 Queries ausfuehrt, von daher kannst du es uebersichtlicher halten, wenn du getrennt selektierst.
(SELECT * FROM foo WHERE id < %id ORDER BY id DESC LIMIT 2)
UNION (SELECT * FROM foo WHERE id >= %id ORDER BY id ASC LIMIT 3) ORDER BY id ASC Lustiger wird das Ganze wenn du nicht ein Sortierkriterium hast, sondern mehrere. Nehmen wir an du hast einen Vornamen (firstname) und einen Nachnamen (lastname) und moechtest nach der Form lastname, firstname sortieren und selektieren. In dem Fall musst du die Sortierung selbst basteln:
SQL-Code:
SELECT * FROM foo WHERE lastname > %lastname OR (lastname = %lastname AND firstname > %firstname) ORDER BY lastname ASC, firstname ASC LIMIT 2
SQL-Code:
Du kannst dir vorstellen, wie sich das Ding aufblaeht, wenn du dann 5 Kriterien drin hast ;)
SELECT * FROM foo WHERE lastname < %lastname OR (lastname = %lastname AND firstname < %firstname) ORDER BY lastname DESC, firstname DESC LIMIT 2
In diesem Fall ist es uebrigens fast immer geschickter, mit 3 Queries zu arbeiten. Schliesslich wird dein Datensatz wohl kaum per Vor- und Nachname definiert werden, sondern per ID. Also musst du dir erstmal die Grenzen aus der Datenbank holen, was in diesem Fall nicht mit einem Subquery oder JOIN gemacht werden sollte, da du ihn gleich zwei Mal machen musst (einmal fuer die vorherigen 2 Datensaetze, einmal fuer die nachfolgenden). Dein DB-Server wirds dir spaetestens ab 4-stelligen Datensatzzahlen danken *g* Greetz alcaeus |
Re: SQL: benachbarte Datensätze mitselektieren
Wow super.
Immerhin nur 2 Abfragen :) Könnte man das Ganze mit Stored Procedures verbessern? EDIT: Mein Fall ist noch ein wenig schwieriger. Mir ist die ID des Users geläufig nach der ich selektieren kann, aber nicht wie groß das Sortierkriterium des Users ist. Also sind es dann doch 3 Abfragen :/ |
Re: SQL: benachbarte Datensätze mitselektieren
Zitat:
SQL-Code:
Das ist aber wieder nur Augenauswischerei, denn der DB-Server wird definitiv drei Queries machen. Du koenntest es ueber nen JOIN loesen, aber dann wirds ab ner gewissen Datensatzmenge einfach haesslich.
SELECT * FROM foo a
WHERE a.sort >= (SELECT sort FROM foo b WHERE id = %id) ORDER BY sort ASC LIMIT 3 Greetz alcaeus Edith sagt: SPs? Keine Ahnung...als eingefleischter MySQL-User komm ich erst seit Kurzem in den Genuss solcher Features und hatte noch nicht die Zeit, mich damit zu befassen :oops: |
Re: SQL: benachbarte Datensätze mitselektieren
SQL-Code:
So ungefähr geht das mit SP unter Firebird. DB wurde nicht angegeben. First heißt woanders eventuell auch Limit oder sonstwie.
for select first 3 M.ID, M.ABDATUM, M.MWSTWERT from MWST8 M
where M.MWSTSATZ = :MWSTSATZ_OUT and M.ABDATUM <= :ABDATUM order by M.ABDATUM desc INTO :ID_OUT,:ABDATUM_OUT,:MWSTWERT_OUT DO SUSPEND; END END ^ |
Re: SQL: benachbarte Datensätze mitselektieren
Ah danke.
Ich versuche es immer noch auf dem klassischen Weg. Mir ist ne Idee gekommen. Ist es möglich ein temporäres Feld einzuführen bei dem die Datensätze laufend nummeriert werden in der reihenfolge in der ich sie bei der 1. Abfrage sortiere? Da könnte ich feststellen an welcher Position sich mein gesuchter datensatz mit Nummern ausgedrückt befindet und danach in einer Unterabfrage den Wertebereich einschränken. |
Re: SQL: benachbarte Datensätze mitselektieren
Verrate uns doch erstmal welches DBMS du benutzt.
|
Re: SQL: benachbarte Datensätze mitselektieren
MySQL :)
|
Re: SQL: benachbarte Datensätze mitselektieren
Es gibt in einer Datenbank keine Reihenfolge, es sei denn man definiert eine. Kannst du mal deine Abfrage beispielhaft zeigen? Wie sieht dein Sortierkriterium aus?
|
Re: SQL: benachbarte Datensätze mitselektieren
SQL-Code:
Da kriegen wir den score her, den der jeweilige User hat
SELECT score
FROM 'user' WHERE 'user_id'= 1 Nun sollen die Daten für diesen User und die 2 nächsten die mehr punkte haben und die 2 die weniger als er haben bestimmt werden
SQL-Code:
SELECT username,score,land
FROM `user` WHERE ?!?!?!? ORDER BY score DESC LIMIT 5; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz