SQL ID ausgeben bis Summe

Skidrow1988

Lieutenant
Registriert
Nov. 2014
Beiträge
943
Servus,

ich hänge gerade etwas fest.

Ich habe eine Tabelle und möchte eine ID ausgegeben bekommen. Als Bedingung möchte ich eine Zahl angeben. z.B. 31
Dann sollte mir die 3 ausgegeben werden. Die zweite Spalte ist also eine Range.
ID 1 ist von 1 - 10
ID 2 von 11 - 30
ID 3 von 31 - 55
ID 4 von 56 - 100


IDRange
110
220
325
445

Natürlich kann die Range variabel sein und die Tabelle erweitert werden. Ich hoffe ich konnte es erklären.

Edit: Die Zahl die ich angeben kann ist in dem Fall von 1 beginnend bis maximal alle Range Werte addiert. In diesem Fall dann 100. Die 31 ist einfach eine Zahl zum erklären.

Ich nutze MariaDB

Vielen Dank:)


Hier gehts zum Antwortpost
 
Zuletzt bearbeitet: (ERLEDIGT)
Also ich verstehs net glaub ich :D Und es fehlt die Information, um welche Datenbank es sich handelt.
Was genau hat die 31 mit deinem Beispiel sein? Was hat es mit dem Range auf sich? Laut deinem Beispiel ist der immer unterschiedlich, mit einer einzigen Query kann das Problem daher unmöglich gelöst werden. Und "dynamisch" schon mal gar nicht.
 
Seine 2. Spalte ist ja ein Wertebereich, er muss also (wenn ich dein Problem richtig verstehe) die Summe der Werte berechnen bis zu der Zeile. Also Zeile 1 u.2 als Summe 30, ist kleiner als sein Wert und dann dritte Zeile dazu ist größer, also Ergebnis 3. Zeile.

In tsql geht sowas wahrscheinlich mit unbounded preceding in einer Windows function.

Allgemein ist ggf ein view die bessere Lösung
 
  • Gefällt mir
Reaktionen: Skidrow1988
Tornhoof schrieb:
Seine 2. Spalte ist ja ein Wertebereich, er muss also (wenn ich dein Problem richtig verstehe) die Summe der Werte berechnen bis zu der Zeile.
Genau so meine ich das. Ich bin kein Anfänger in der Geschichte aber habe gerade keine Idee.
 
Folgende Ideen hätte ich:
1. Self join anhand id und (id - 1) wobei irgendwo da ein case/if rein muß um das Ganze => 1 zu halten. Damit dann an die Relation ein range_min, range_max anfügen, wobei eins halt an Stelle (id-1) ist und das andere an Stelle (id).

2. Ranking Funktion. Ist es ja letztlich bereits. Allerdings keine Ahnung ob das DBMS eine Rankingfunktion mit Expression als Input unterstützt.

3. Ich möchte behaupten daß man mit einem window und partition by ebenfalls zum Ziel kommen sollte. Aber das ist eher grad so ein lautes Bauchgefühl.
 
In TSQL siehts dann so aus:

SQL:
SELECT TOP 1 Id FROM (
SELECT
    Id, SUM([Range]) OVER (ORDER BY [Id] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RangeSum
FROM Test) x WHERE RangeSum > 30

Anmerkung: Ich habe keine Ahnung wie intelligent SQL Server dabei ist, bei größeren Datenmengen sollte man das ziemlich sicher in einen View packen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Skidrow1988 und Iqra
Der einfachste Ansatz wäre wohl

ID | low | high

Mir würde jedenfalls auch nichts einfallen, ohne mir die Finger zu brechen. Vielleicht kannst du auch etwas ausholen wofür oder warum nur die Distanzen benötigt werden.
Skidrow1988 schrieb:
und die Tabelle erweitert werden
 
Hier mal ein Beispiel wie man es mit SQL (ohne Windows functions) lösen könnte. Hab es schnell auf dem Handy getippelt, daher wegen der Formatierung nicht meckern. Nur noch den Filter hinzufügen, dass der Wert zwischen range_start und range_end liegen soll.

https://www.db-fiddle.com/f/xm5MYvt72srqxNLftYdw47/2

Edit: Hatte noch einen kleinen Fehler drin.

Edit2: Habe es mal verschönert
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Skidrow1988
Bei der Tabellenstruktur ist das nichts was ich noch mit SQL lösen würde, sondern in der Applikation die Tabelle abfragen und per (Skript-)Sprache auswerten. Bin aber auch nicht der SQL Profi.
 
  • Gefällt mir
Reaktionen: Raijin
@marcOcram
Danke, werde ich gleich Mal testen. 🙂 Muss es gleich für mich Mal richtig formatieren. Auf dem Handy bin ich gerade nicht durchgestiegen 😂

@Drexel
Das würde ich auch hinbekommen, aber wieso diesen Umweg, wenn SQL das schon kann. Am Anfang habe ich genau diesen Fehler sehr oft gemacht.

@Tornhoof
Danke dir, auch deins teste ich gleich Mal. Wobei du definitiv fitter in der Materie bist als ich 🙂
 
Tornhoof schrieb:
In TSQL siehts dann so aus:

SQL:
SELECT TOP 1 Id FROM (
SELECT
    Id, SUM([Range]) OVER (ORDER BY [Id] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RangeSum
FROM Test) x WHERE RangeSum > 30

Anmerkung: Ich habe keine Ahnung wie intelligent SQL Server dabei ist, bei größeren Datenmengen sollte man das ziemlich sicher in einen View packen.


Das hat funktioniert! Ich sage vielen vielen Dank! Ich musste logischerweise 'range' umbenennen. In der Demo habe ich es in 'ranges' umbenannt. Range ist ja bereits belegt und kann deshalb nicht benutzt werden. Die TOP Funktion gibt es in MariaDB nicht. Das habe ich durch ein LIMIT 1 ersetzt. Wobei dies eigentlich nicht muss. Es gibt ja immer nur ein richtiges Ergebnis. Danke an alle die mir geholfen haben!

SQL:
SELECT id FROM (
SELECT
    id, SUM(ranges) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RangeSum
FROM spiel.test) x WHERE RangeSum > 30 LIMIT 1
 
marcOcram schrieb:
ohne Windows functions
😜
Es sind WINDOW functions, wie Fenster, nicht wie das Betriebssystem und die sind teil von SQL ;) Geht in dieselbe Richtung wie Aggregatfunktionen, nur daß sie halt nicht aggregieren, sondern ihr Ergebnis konkret Zeilen zuteilen und da dann ein spezifisches Fenster auf die Daten berücksichtigen (können). Daher auch der Name.
Beispiel, du willst einen Durchschnittswert über die letzten 100 Werte haben.
Oder halt @Tornhoof s Implementierung über "alle vorhergehenden Zeilen ("between unbounded preceding and current", dh. alle vorhergehenden Zeilen bis zur aktuellen, wobei hier natürlich ein Ordnung erforderlich ist, um das "vorhergehend" definieren zu können).
 
  • Gefällt mir
Reaktionen: Skidrow1988
Zurück
Oben