SQL Ein Raum-Zeit-Prrroblem

Status
Für weitere Antworten geschlossen.
A

Anjacom

Gast
Ich habe Datensätze wie folgt:

item_id, item_date
int, timestamp int


Um es anschaulicher zu machen, nehme ich Wochentage anstelle des Timestamps und setze die Position vorne dran mit #

Die Sortierung ist item_date ASC, item_id ASC

Zustand:
#1 - Montag - 12
#2 - Mittwoch - 22
#3 - Freitag - 10

Jetzt soll die item_id 10 an die zweite Stelle verschoben werden, also

Ändere item_date auf Dienstag, wo item_id = 10

Ergebnis
#1 - Montag - 12
#2 - Dienstag- 10
#3 - Mittwoch - 22


Problematisch wird es jetzt:
#1 - Montag - 12
#2 - Montag - 22
#3 - Freitag - 10

Ich kann die item_id 10 nicht an die Position zwei setzen ohne item_date der anderen Datensätze zu ändern.
Kein Problem, ich fange hinten an und sage

Für alle Datensätze, nehme den letzten und setze auf Sonntag.
Nehme den Datensatz davor und setze auf Freitag (jeweils ein Tag frei dazwischen)
usw.

Mal angenommen, dass ich 10.000 Datensätze habe und #8992 auf #4 setzen will.
Mal angenommen, ich habe das schon ziemlich oft gemacht, meine Timestamps könnten nahe beieinander liegen.

Was wäre die optimale Lösung, um das Datum neu zu verteilen?
Ich möchte jetzt nicht hinten anfangen und alle 10.000 Datensätze updaten.

Idee 1:
Gehe von Zielort, Position # soweit nach oben bis eine Position gefunden wird, wo der zeitliche Abstand groß genug ist, dass ich alle item_date dazwischen mit einem Abstand von 10 neu setzen kann.


Wie könnte so eine Query aussehen?

Finde die Zeile, wo der Wert item_date größer ist als die Anzahl der Zeilen zwischen #4 und x bei einer gewünschten Different von 10.
Kann man das umsetzen?
Hmmm, da ich die Position auch als Feld habe:

Zeitdifferenz_notwendig = (Position_gesucht - Position_ Ziel) * 10
Zeitdifferenz_ist = (date_gesucht - date_ Ziel)

Select from table where {Zeitdifferenz} and {Zeitdifferenz_ist}

select from table
where position = (position - 4) AND date = (position-4)*10


Geht das in mysql?

Oder muss ichj via php solange durchlaufen bis ich eine passende Zeile finde?



Idee 2:
Schaue nach #4 und #5, ist da Platz dazwischen?
Dann schiebe #8992 nach #4 mit einem item_date = Hälfte des Abstandes von #4 und #5 alt.

Sind #4 und #5 gleich, dann erhöhe item_date von #5 um 10, schiebe die #8992 wieder zwischen #4 und #5 alt,
prüfe nun die #6, ist item_date von #6 > item_date von #5?
Wenn nein, erhöhe item_date von #6

Mache das solange bis es passt und item_date von x > item_date von x-1


Das kann ich umsetzen; schlimmstenfalls (aber eher nur theorethisch) muss ich alle Zeilen durchlaufen, habe dann aber wesentlich mehr Abfragen als bei einer Lösung, die item_date gleich neu setzt.

Das wäre dann Idee 3, nämlich setze einfach alle Zeilen passend neu.


Sollte man stattdessen alle paar Tage mal nachts einen cron-job laufen lassen, der eine ganze Liste zeitlich neu setzt, so dass man immer Platz zum Schieben hat?


Das Problem ist wie es ist, es muss mit den Vorgaben gelöst werden.

Ich hoffe, dass das nur eine kleine Fingerübung für jemanden ist, mir fallen so weit keine besseren Lösungen ein.
 
Anjacom schrieb:
Das Problem ist wie es ist, es muss mit den Vorgaben gelöst werden.
Ich verstehe trotzdem nicht was das Ziel ist. Die Datensätze haben einen Timestamp, der wohl eine bestimmte Bedeutung hat, bspw. wann der Datensatz erstellt oder zuletzt geändert wurde. Warum kannst du den einfach verändern? Wenn sie nur der Sortierung dient, warum heißt die Spalte dann nicht sorting o.ä.?

Jedenfalls was ich machen würde:
Code:
ALTER TABLE items ADD COLUMN sorting INT(11) UNSIGNED;

UPDATE items SET sorting = ROW_NUMBER() * 2;

UPDATE items SET sorting = 3 WHERE item_id = 10;

UPDATE items SET sorting = ROW_NUMBER() * 2 ORDER BY sorting;

Und in Zukunft halt nur noch ORDER BY sorting verwenden.

Kannst du im Zweifel ja an deine Bedingungen anpassen.
 
  • Gefällt mir
Reaktionen: Mip101, imRa und elefant
Bei aller Liebe und gebotenen Freundlichkeit - was verstehst Du nicht an der Vorgabe?

Das Problem ist wie es ist, es muss mit den Vorgaben gelöst werden.

Ist das so schwer zu verstehen bzw. zu akzeptieren, dass ich genau dieses Problem lösen muss? Muss man da diskutieren? Noch dazu mit einem, der "Physik" als Bestandteil in seinem Namen hat? Betrachte die Vorgaben als Naturgesetz und dann kannst/willst Du es lösen und hast evtl. was dazu zu sagen, oder halt auch nicht, dann wende Dich doch gerne einer anderen Sache zu.

Wenn ich irgendwas anpassen könnte, würde ich das machen. Aber ich kann nicht, will nicht, werde nicht. Es geht um vielfach größeres System, das ist wie es ist. Und innerhalb dieses Systems muss/will ich was sortieren. Das Datum spielt dabei keine Rolle. Und wenn es für Dich beschwerlich ist, denn Sprung im Kopf zu machen, dann vergiss einfach, dass das Feld item_date heißt und nenne es item_sortier_integer oder auch item_sorting, denn es ist nichts anderes als eine Integer-Zahl.


Man ist dann übrigens bei genau der gleichen Aufgabenstellung!

item_sorting, item_id

Zustand:
#1 - 100 - 12
#2 - 120 - 22
#3 - 140 - 10

Schiebe id 10 an position #2

#1 - 100 - 12
#2 - 110 - 10
#3 - 120 - 22

Hurra, aber, was wenn ...

#1 - 100 - 10
#2 - 100 - 12
#3 - 100 - 22

Wie kann ich id 22 and pos #2 setzen?

Klar, mit Änderung von item.sorting

#1 - 90- 10
#2 - 100 - 22
#3 - 110 - 12

Was aber, wenn ich 10.000 Datensätze habe und #9880 an #4 schieben will?

Was, wenn es dort heißt:

#1 - 100- 10
#2 - 100 - 22
#3 - 100 - 12
#4 - 100 - 13
#5 - 100 - 14
#6 - 100 - 15
...
#1000 - 100 - 1009
Ergänzung ()

Ansonsten ist das hier Idee 3

UPDATE items SET sort_feld= ROW_NUMBER() * 2;

Aber das bedeutet auch, dass 10.000 Zeilen neu geschrieben werden müssen.

Und wenn man etwas an die #pos4 setzt, dann müssen alle Zeilen ab #4 neu berechnet werden.
Also immer noch 10.000-3 Datensätze zur Berechnung.

Wenn wir aber davon ausgehen, dass zwischen den meisten Werten im Sortierfeld ein Wert von zwischen 10^2 und 10^4 liegt und ich nur ab und an was schieben muss, dürfte es meistens keine Probleme geben.

Ergo:

move #x nach #y, checke #y-1 und #y, ob dazwischen Platz ist, wenn ja move.

Wenn kein Platz ist?
Checke, ob man es über die ID lösen kann.

Wenn das nicht möglich ist?
Checke

a) solange Sortierwert erhöhen bis #n < #n+1
b) schlaue query finden, die mir #n+1 raussucht, so dass ich alle Sortierwerte zwischen #4 und #n neu setze und hoffentlich nur ein paar Zeilen updaten muss.

Unterschied a) und b)

b) query zum finden und dann #n-4 queries für updates
a) query zum Vergleich und query zum update; grob doppelt so viele queries

Es bleibt also die Frage, ob diese query möglich ist:

Gegeben

position
item_id
item_sortier_integer

und Quell- und Zielposition eines items; z.B. 9982 nach 4

finde die item_id x bei der die Differenz zwischen x_sortierfeld und alt4.sortierfeld = Schrittgröße mal (position von x - position von 4)

select id from table
where (sort_feld_value-sort_feld_value von pos4) = 10 * (position_feld_value-4)
order by position asc
limit 1
Ergänzung ()

Und jetzt gehe ich das mal am lebenden Objekt testen.
 
Zuletzt bearbeitet von einem Moderator:
Ich bin komplett bei @Physikbuddha ,deine Datenbank macht so absolut keinen Sinn.
Das merkst du ja gerade selber, weil du nichtmal etwas sortieren kannst.
Lösch die am besten und fang auf einem weißen Papier neu an

Edit: Wenn ich schon sehe das du eine Sortier-ID hast die bei mehreren Datensätzen gleich ist ... :`(
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: imRa, steff0rn und ThunderbirdOP
Habe deinen Text nur überflogen, da er fürchterlich formatiert ist und viel Text ohne Aussage enthält. Es gibt übrigens nicht umsonst Tabellendiagramme und code tags.

Ich werde das Gefühl nicht los, dass es sich um eine Hausaufgabe handelt… einen Lösungsvorschlag hast du bereits von Physikbuddha erhalten. Wenn es sich um eine reales Anwendungsszenario halten sollte, dann mach das, was elefant geschrieben hat und unterlasse solche Fummeleien.
 
Das System, von dem ich rede, heißt Xenforo, das ist ein Forensystem, wir nutzen es gerade.

Für dieses System gibt es ein wunderbares Add-on, für das ich die Idee geliefert habe. Leider war der Programmierer faul und bequem und hat es nicht in letztes Konsequenz umgesetzt. Also muss ich das machen.

Und dazu gehört die Lösung des oben genannten Problems.

Edit: Wenn ich schon sehe das du eine Sortier-ID hast die bei mehreren Datensätzen gleich ist ... :`(
Dann siehst Du was genau? Ein Beispiel, das völlig überspitzt das Problem darstellen soll.

einen Lösungsvorschlag hast du bereits von Physikbuddha erhalten
Ja, habe nicht. Es ist sicherlich die schlechteste Lösung.


Gibt es hier hilfreiche Programmierer im Forum, die etwas Konstruktives beisteuern können?
 
Zuletzt bearbeitet von einem Moderator:
Ich würde mir an deiner Stelle die Frage stellen wer "etwas Konstruktives beizusteuern" möchte wenn deine "Liebe und gebotene Freundlichkeit" aus herablassenden Umgang mit Freiwilligen besteht. Erst recht nicht, wenn es sich um eine vage Aufgabenstellung handelt, die auch ein X/Y-Problem sein könnte. Warum möchtest du nicht erklären worum es dabei genau geht? Gehst du zum Arzt und sagst "Herr Doktor, ich habe Kopfweh, ich brauche eine Lobotomie! Diese Vorgabe ist ein Naturgesetz!" :D
 
  • Gefällt mir
Reaktionen: Physikbuddha, Myron, Mip101 und 2 andere
Physikbuddas Lösung ist wunderbar. Einfach, nachvollziehbar und vor allem performant.

Diese Art einer sorting Spalte wird immer wieder gerne verwendet um eine bestimmte Sortierungslogik erzwingen zu können.
Ich würde sorting beim ersten Erstellen der Spalte nur anders berechnen, z.B. als Multiple von 64.

item_id, item_sorting
1, 0
2, 64
3, 128
4, 192
5, 256

Wenn du ID 3 lieber woanders einsortiert haben möchtest, schiebst du das über item_sorting genau in die Mitte deines Ziels.

item_id, item_sorting
1, 0
2, 64
4, 192
3, 224
5, 256

Du scheinst nicht gerade Ahnung von SQL zu haben und behauptest diese Lösung sei die schlechteste.
I lol'd.
 
Vor allem ist die Vorgabe nichts verändern zu dürfen nur künstlich herbei geführt. Bei einem eigenen Add-On und vollem Datenbankzugriff kann man sich die Freiheiten nehmen, die man eben dafür braucht. Es tut vielleicht weh, wenn man viel Zeit und Arbeit in den falschen oder komplizierten Weg investiert hat, aber ihn dafür trotzdem weiter zu gehen macht keinen Sinn. Darum erstellt man sich erst komplette Konzepte in Theorie und verfeinert diese soweit, bis man sie programmatisch quasi nur runter schreiben muss. Die Denkarbeit vor der Handarbeit. Genauer helfen kann ich an dieser Stelle aber auch nicht, da ich hier mit gutem Ton bezahlt werden möchte und das Budget erschöpft scheint... zumal ich nur abweichende Ansätze liefern würde, die aber dem TE nicht schmecken würden.
 
Herrlich, herrlich, so stelle ich mir das neue Deutschland vor in wenigen Jahren.

Da fragst Du einen Elektriker, der dir dann nicht die Leitung repariert will, sondern erklärt, dass du erst mal das Haus umbauen sollst. Wenn du ihm dann sagst, dass das ganz schön vermessen sei, was er da erzähle, wird er dir damit kommen, dass er ja gerne helfen würde und das auch könne, aber bei so viel Unfreundlichkeit nicht mehr wolle. Und außerdem seien Stromkabel sowieso doof, man müsse diese Geräte halt auch mal abschaffen und stattdessen lernen wie man seinen Namen tanzen kann.

Währenddessen kommt ein anderer Schimmelkleber und erzählt dir, dass sowieso keine Leitungen mehr gebraucht würden, denn man müsse nur alles schön feucht halten, damit der Strom fließt. Und dass das so sei wegen des Koboldes, der den Stromzufluss aus den Steckdosen verwalte.

Der nächste Schnarcher meint zu allem, alles Quatsch, er habe die Lösung! Man brauche doch nur Batterien kaufen, und notfalls halt in Schaltungen reihen, und zwar immer in 64er-Blöcken, er habe schließlich Abitur gemacht und das sogar in Berlin.



In diesem Sinne:

Gegeben sind

xf_post alias post
.post_id
.post_date

Die Sortierung erfolgt über post_date ASC, post_id ASC, Beiträge sollen beliebig von A nach B verschoben werden. Die Beibehaltung des Datums ist ausschließlich für den ersten und den letzten Beitrag wichtig.

Finde eine Lösung dafür, dass zwischen der Zielposition und dem Nachfolgebeitrag für post_date eine Differenz von 1 oder 0 besteht. Die Lösung soll auch funktionieren, wenn alle Beiträge ein und dasselbe Datum haben. Achte dabei auf eine möglichst geringe Anzahl an queries.
 
Zuletzt bearbeitet von einem Moderator:
Die Art des TEs ist unterirdisch, Nettigkeit muss hier wohl noch erfunden werden.
Ich mache den Thread zu, so wird das nichts.
 
  • Gefällt mir
Reaktionen: Oelepoeto, elefant, Tr3x und 6 andere
Status
Für weitere Antworten geschlossen.
Zurück
Oben