Position eines Datensatzes innerhalb eines Resultsets feststellen

Position eines Datensatzes innerhalb eines Resultsets feststellen

am 27.06.2007 13:41:08 von Marcus Schwarz

Aloha *,

folgende Situation: Ich habe ein segmentiertes Resultset als Ergebnis
einer Abfrage. Dieses Ergebnis ist teilweise "unsortiert", da das
Sortierkriterium bei manchen Ergebnissen den gleichen Wert hat. Nun
müsste ich aber feststellen, an welcher Stelle in diesem Resultset sich
ein bestimmter Datensatz befindet. Bisher war die Lösung:

Mithilfe einer zweiten Abfrage die Anzahl der Datensätze bestimmen,
welche vor dem eigentlich gesuchten Datensatz sein müssten. Das aber
funktioniert eben genau bei gleichen Werten im Suchkriterium nicht.

Eine weitere Variante die mir einfällt wäre einfach eine Schleife über
das gesamte Resultset und per String-Vergleich nach dem entsprechenden
Eintrag suchen. Das erscheint mir nicht sonderlich effektiv, da das
Resultset gigantisch werden kann.

Beide bisherigen Lösungen sind also nicht zufriedenstellend. Gibt es
eine bessere Lösung? Da ich gerne zu umständlichen Umschreibungen neige,
hier ein einfaches Beispiel:

Datenbank:
name wert
jkl 1
ghi 1
abc 2
stv 1
mno 1
def 1
pqr 1


Resultset unsegmentiert:
name wert
abc 2
stv 1
ghi 1
jkl 1
def 1
pqr 1
mno 1

das ganze per limit segmentiert in folgende resultsets:
name wert
abc 2
stv 1

ghi 1
jkl 1

def 1
pqr 1

mno 1


gesucht: der Rang des Eintrags jkl im unsegmentierten Resultset:
Variante a) liefert: 2
Variante b) liefert: 4

Variante b) liefert also die korrekte Position, aber der Aufwand wäre
sehr hoch.

Ich hoffe ich konnte verdeutlichen, wofür ich eine Lösung suche :)

Danke & Grüße
Marcus
--
"Es ist leichter einer Begierde zu entsagen, als in ihr Maß zu halten."
Friedrich Nietzsche

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 27.06.2007 15:37:24 von Niels Braczek

Marcus Schwarz schrieb:

> Ich hoffe ich konnte verdeutlichen, wofür ich eine Lösung suche :)

Jein. Willst du tatsächlich die *Position* wissen oder auf den Datensat=
z
zugreifen können?

$sql =3D "SELECT name, wert FROM table";
$result =3D mysql_query( $sql ) or die( $sql.'
'.mysql_error() );

$rows =3D array();
while ( $row =3D mysql_fetch_assoc( $result ) ) {
$rows[ $row->name ] =3D $row;
}

Jetzt findest du in $rows jeden gesuchten Eintrag, zB. $rows['jkl'],
ohne seine Position zu kennen.

Willst du tatsächlich die Position wissen, dann

$pos =3D array_flip( array_keys( $rows ) );

In $pos['jkl'] steht die position des Eintrags 'jkl'.

MfG
Niels

--=20
| http://www.kolleg.de =B7 Das Portal der Kollegs in Deutschland |
| http://www.bsds.de =B7 BSDS Braczek Software- und DatenSysteme |
| Webdesign =B7 Webhosting =B7 e-Commerce =B7 Joomla! Content Management =
|
------------------------------------------------------------ ------

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 27.06.2007 16:26:06 von Claus Reibenstein

Marcus Schwarz schrieb:

> Ich habe ein segmentiertes Resultset

Was ist ein "segmentiertes Resultset"?

> Dieses Ergebnis ist teilweise "unsortiert", da das
> Sortierkriterium bei manchen Ergebnissen den gleichen Wert hat.

Dann nimm eben ein zweites Sortierkriterium dazu.

> Nun müsste ich aber feststellen, an welcher Stelle in diesem Resultset sich
> ein bestimmter Datensatz befindet.

Was meinst Du mit "an welcher Stelle"?

> Da ich gerne zu umständlichen Umschreibungen neige

Ich würde eher sagen: zu unverständlichen Umschreibungen.

> gesucht: der Rang des Eintrags jkl im unsegmentierten Resultset:

Was verstehst Du unter "Rang"?

> Variante a) liefert: 2
> Variante b) liefert: 4
>
> Variante b) liefert also die korrekte Position, aber der Aufwand wäre
> sehr hoch.

Wobei mir nicht klar ist, was an der 4 "korrekter" sein soll als an der 2.

> Ich hoffe ich konnte verdeutlichen, wofür ich eine Lösung suche :)

Nicht wirklich.

Gruß. Claus

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 28.06.2007 18:37:41 von Marcus Schwarz

Claus Reibenstein schrieb:
> Was ist ein [...]
> Was meinst Du mit [...]
> Ich würde eher sagen: zu unverständlichen Umschreibungen.
> Was verstehst Du unter [...]

ok, ich gebe zu, das war unverständlich für Außenstehende :)
Lass es mich bitte nochmal versuchen anhand eines umfangreicheren Beispiels:

Ich möchte eine Rangliste erstellen, beispielsweise eine Highscore-Liste
(Daher "Rang"). In einer solchen Rangliste können ja x Spieler die
gleiche Punktzahl haben (Die "1" in meinem Beispiel). Solange alle
Spieler unterschiedliche Punktzahlen haben, ist das Problem trivial.
Weil nun aber x = >400 Spieler die gleiche Punktzahl haben und ich auf
jeder Seite nur y << 400 Einträge anzeigen kann, dem Spieler aber die
Möglichkeit geben will, direkt zu der Seite zu springen, auf der sein
Eintrag steht, benötige ich die Möglichkeit, diese Position festzustellen.

Das Problem dabei ist, dass das einzige Sortierkriterium, welches zur
Verfügung steht, die Punktzahl ist. Ein Datum als weiteres Kriterium
oder eine ID, anhand derer man sich orientieren könnte, steht nicht zur
Verfügung.

Nun gibt ja MySQL die Ergebnisse in einer bestimmten Reihenfolge aus,
auch innerhalb der gleichen Punktzahlen ändert sich die Reihenfolge über
z Anfragen hinweg nicht. Obwohl das Ergebnis also eigentlich eine
ranglose Menge ist scheint MySQL intern in irgendeiner Art und Weise zu
sortieren. Ich vermute an dieser Stelle, dass die Einfügezeit in die
Indexdatei etwas damit zu tun hat. Je später der Eintrag erfolgt ist,
desto "weiter hinten" in der Tabellendatei ist der entsprechende Eintrag
zu finden.

Nun hat Niels ja eine Möglichkeit geschrieben, über das gesamte
Resultset den entsprechenden Eintrag mittels einer while-Schleife zu
suchen. Das wäre möglich, ist aber aufgrund der Größe der zu
untersuchenden Tabelle nicht praktikabel, da sie mehr als 500.000
Einträge hat. Das würde ja bedeuten, bei jedem Aufruf einer Seite der
oben genannten Highscore-Liste zunächst die gesamte Tabelle auszulesen.
Das wäre das Ende für die Anwendung.
Es muss doch also eine mysql-serverseitige Lösung geben, welche das
Ergebnis quasi durchnummeriert. Das nimmt man dann als Subselect und
kann dann ganz einfach diesen Rang auslesen.

Ich hoffe, ich habe nun weniger Fragezeichen hinterlassen. Falls doch
geh ich wohl besser doch wieder in den Sandkasten spielen :)

m*
--
"Wenn das Leben eine Zitrone ist - mach Limo daraus"
Bernhard Pompey

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 28.06.2007 18:54:32 von Claus Reibenstein

Marcus Schwarz schrieb:

> Das Problem dabei ist, dass das einzige Sortierkriterium, welches zur
> Verfügung steht, die Punktzahl ist.

Wieso? Hat Deine Tabelle nur eine einzige Spalte? Deine Beispieltabelle
in <46824c66$0$14881$9b4e6d93@newsspool4.arcor-online.net> hatte
jedenfalls zwei. Somit hast Du auch schon mal mindestens zwei
Sortierkriterien zur Verfügung.

> Ein Datum als weiteres Kriterium
> oder eine ID, anhand derer man sich orientieren könnte, steht nicht zur
> Verfügung.

Und ob die zur Verfügung steht. _Jede_ Spalte einer Tabelle kann zur
Sortierung herangezogen werden.

> Nun gibt ja MySQL die Ergebnisse in einer bestimmten Reihenfolge aus,
> auch innerhalb der gleichen Punktzahlen ändert sich die Reihenfolge über
> z Anfragen hinweg nicht.

Wer sagt das? Das Handbuch? Die Online-Dokumentation?

Die Reihenfolge ist zufällig und durch nichts festgelegt. Sich darauf
verlassen zu wollen, halte ich für _sehr_ gewagt.

> Obwohl das Ergebnis also eigentlich eine
> ranglose Menge ist scheint MySQL intern in irgendeiner Art und Weise zu
> sortieren.

MySQL sortiert genau nach den Kriterien, die Du angibst.

Gruß. Claus

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 28.06.2007 19:15:32 von Marcus Schwarz

Claus Reibenstein schrieb:

> Wieso? Hat Deine Tabelle nur eine einzige Spalte? Deine Beispieltabelle
> in <46824c66$0$14881$9b4e6d93@newsspool4.arcor-online.net> hatte
> jedenfalls zwei. Somit hast Du auch schon mal mindestens zwei
> Sortierkriterien zur Verfügung.

Nein, aber die anderen Felder taugen auch nicht zur Sortierung, da auch
diese nicht zwingend einzigartig sein müssen. Würde ich nach Name
sortieren würde die bestehende Sortierung über den Haufen geworfen, was
nicht sein darf.

> Wer sagt das? Das Handbuch? Die Online-Dokumentation?

Die entsprechende Rangliste, die seit Monaten im Bereich 0 Punkte in
identischer Reihenfolge steht, obwohl das Ergebnis nirgends gecached wird.

> Die Reihenfolge ist zufällig und durch nichts festgelegt. Sich darauf
> verlassen zu wollen, halte ich für _sehr_ gewagt.

Ich will mich darauf nicht verlassen, es ist aber das einzige, was mir
als taugliches Kriterium erscheint.

> MySQL sortiert genau nach den Kriterien, die Du angibst.

Und welche sind das dann wenn ich sage "ORDER BY punkte DESC" und dann
400 mal die gleiche Punktzahl kommt? Wie gesagt, das Ergebnis dieser
Abfrage ist eben über viele Abfragen hinweg immer identisch, daher die
Vermutung dass da was dahinter steht.

m*


--
"Demokratie ist ein Verfahren, das garantiert, daß wir nicht besser
regiert werden, als wir es verdienen."
George Bernard Shaw

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 28.06.2007 19:40:50 von Claus Reibenstein

Marcus Schwarz schrieb:

> Claus Reibenstein schrieb:
>
>> Wieso? Hat Deine Tabelle nur eine einzige Spalte? Deine Beispieltabelle
>> in <46824c66$0$14881$9b4e6d93@newsspool4.arcor-online.net> hatte
>> jedenfalls zwei. Somit hast Du auch schon mal mindestens zwei
>> Sortierkriterien zur Verfügung.
>
> Nein, aber die anderen Felder taugen auch nicht zur Sortierung, da auch
> diese nicht zwingend einzigartig sein müssen. Würde ich nach Name
> sortieren würde die bestehende Sortierung über den Haufen geworfen, was
> nicht sein darf.

Und wenn Du nach Punktzahl _und_ Namen sortierst? Also etwa ORDER BY
punkte DESC, name ASC? Dann wird nach Punktzahlen sortiert und innerhalb
gleicher Punktzahlen nach Name. Ist das nicht genau das, was Du möchtest?

>> Wer sagt das? Das Handbuch? Die Online-Dokumentation?
>
> Die entsprechende Rangliste, die seit Monaten im Bereich 0 Punkte in
> identischer Reihenfolge steht, obwohl das Ergebnis nirgends gecached wird.

Also schlussfolgerst Du lediglich aus eigener Beobachtung. Wer sagt Dir,
dass diese Schlussfolgerung richtig ist?

>> Die Reihenfolge ist zufällig und durch nichts festgelegt. Sich darauf
>> verlassen zu wollen, halte ich für _sehr_ gewagt.
>
> Ich will mich darauf nicht verlassen, es ist aber das einzige, was mir
> als taugliches Kriterium erscheint.

Und genau das halte ich für Unfug.

>> MySQL sortiert genau nach den Kriterien, die Du angibst.
>
> Und welche sind das dann wenn ich sage "ORDER BY punkte DESC" und dann
> 400 mal die gleiche Punktzahl kommt?

Du sollst ja auch nicht nur nach der Punktzahl sortieren, sondern ein
weiteres Kriterium hinzunehmen. Was ist daran so schwer zu kapieren?

Gruß. Claus

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 29.06.2007 09:37:41 von dev-null-use-reply-adress

Claus Reibenstein schrieb:
> Marcus Schwarz schrieb:
>
>> Claus Reibenstein schrieb:
>>
>>> Wieso? Hat Deine Tabelle nur eine einzige Spalte? Deine Beispieltabelle
>>> in <46824c66$0$14881$9b4e6d93@newsspool4.arcor-online.net> hatte
>>> jedenfalls zwei. Somit hast Du auch schon mal mindestens zwei
>>> Sortierkriterien zur Verfügung.
>>
>> Nein, aber die anderen Felder taugen auch nicht zur Sortierung, da auch
>> diese nicht zwingend einzigartig sein müssen. Würde ich nach Name
>> sortieren würde die bestehende Sortierung über den Haufen geworfen, was
>> nicht sein darf.
>
> Und wenn Du nach Punktzahl _und_ Namen sortierst? Also etwa ORDER BY
> punkte DESC, name ASC? Dann wird nach Punktzahlen sortiert und innerhalb
> gleicher Punktzahlen nach Name. Ist das nicht genau das, was Du möchtest?

Genau das hätte ich auch gesagt. Die Sortierung nach Punkten bleibt
und wenn es hunderte mit der selben gibt, finden sich die Betroffenen
trotzdem schnell.
Marcus, was gefällt Dir daran nicht?


Gruß
JPM

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 29.06.2007 19:00:24 von Marcus Schwarz

Jens Peter Moeller schrieb:

> Marcus, was gefällt Dir daran nicht?

Dass die bisherige Sortierung innerhalb eines Rangs nicht bestehen
bleibt sondern komplett neu zusammengewürfelt wird. Das geht nicht.

marcus
--
"Fortschritt ist eine Verwirklichung von Utopien."
Oscar Wilde

Re: Position eines Datensatzes innerhalb eines Resultsets feststellen

am 30.06.2007 04:03:52 von Niels Braczek

Marcus Schwarz schrieb:
> Jens Peter Moeller schrieb:
>=20
>> Marcus, was gefällt Dir daran nicht?
>=20
> Dass die bisherige Sortierung innerhalb eines Rangs nicht bestehen=20
> bleibt sondern komplett neu zusammengewürfelt wird. Das geht nicht.

Du hattest bisher keine Sortierung innerhalb eines Ranges, sondern eine
rein zufällige Folge.

Wenn du die Wiederholbarkeit dieser zufälligen Folge auch bei Verwendun=
g
von LIMIT sicherstellen willst, musst du eine neue Spalte `ordering`
einführen, in der du die jeweilige Position in der zufälligen Folge
festhältst. Diese Spalte kannst du dann künftig zum Sortieren benutze=
n.
Das aber ist ein reines MySQL-Problem.

MfG
Niels

--=20
| http://www.kolleg.de =B7 Das Portal der Kollegs in Deutschland |
| http://www.bsds.de =B7 BSDS Braczek Software- und DatenSysteme |
| Webdesign =B7 Webhosting =B7 e-Commerce =B7 Joomla! Content Management =
|
------------------------------------------------------------ ------