Kleinster Wert

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Hallo zusammen,

ich arbeite mit SQLite und möchte den kleinsten Wert einer Summe berechnen. Hier mein Beispiel

Code: Alles auswählen

A    B
1    3
2    3
3    6
Meine bisherige Abfrage war

Code: Alles auswählen

select sum(B-A) AS C from MeineTabelle
Dann erhalte ich als Ergbnis

Code: Alles auswählen

C
2
1
3
Wenn ich dann den kleinsten Wert des Ergebnisses (hier dann 1) haben möchte, wie kann ich das denn machen?

Ich habe schon versucht ein min() vor die Summe zu setzen, aber da hab ich einen Error bekommen. Mit WHERE hab ich es auch schon versucht, hatte aber keinen Erfolg.

Hat jemand eine Idee, wie man das machen könnte?
Bin für jeden Hinweis dankbar.

Gruß Isa
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Ich habe es gerade eben doch noch gefunden. Das Statement lautet dann

Code: Alles auswählen

select sum(B-A) as C from MeineTabelle limit 1
Zuletzt geändert von maria_dolores am Dienstag 14. September 2010, 08:49, insgesamt 1-mal geändert.
BlackJack

@maria_dolores: Das wäre dann aber nur Zufall wenn dabei das richtige Ergebnis herauskommt. Das sagt ja nur, dass das Ergebnis auf einen Datensatz beschränkt werden soll, aber nicht *welcher* Datensatz das sein soll.
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

maria_dolores hat geschrieben:Hallo zusammen,
Meine bisherige Abfrage war

Code: Alles auswählen

select sum(B-A) AS C from MeineTabelle
Dann erhalte ich als Ergbnis

Code: Alles auswählen

C
2
1
3
"Ich glaube nicht, Tim" ;)
Diese Abfrage liefert genau einen Tupel zurück und zwar die Summe jeder Tupel von Spalte B minus Spalte A. Sum ist eine Aggregatfunktion, da können nicht mehrere Tupel zurückgeliefert werden, zumindest nicht mit deinem SQL-Beispiel
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Hallo,

danke.. Ich wäre sonst davon ausgegangen, dass das mit limit funktioniert. Mein Datensatz hätte am Ende noch ein ORDER BY enthalten sollen. Das hatte ich vergessen hinzuschreiben. Dann wäre das Ergebnis der Abfrage

Code: Alles auswählen

C
1
2
3
Ist denn ein ORDER BY in Kombination mit LIMIT die kürzeste Möglichkeit den kleinsten Wert zu bekommen oder gibt es da eine Funktion für?

Gruß Isa
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

maria_dolores hat geschrieben:Ist denn ein ORDER BY in Kombination mit LIMIT die kürzeste Möglichkeit den kleinsten Wert zu bekommen oder gibt es da eine Funktion für?
Die Verwendung von ORDER BY mit LIMIT für diese Aufgabe ist nicht wirklich schön. Ich würde einfach

Code: Alles auswählen

SELECT MIN(b-a) AS c FROM meinetabelle
verwenden.
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Danke an alle. Hat mir alles sehr geholfen.

Ich habe da gleich noch eine Frage. Meine Tabelle sieht momentan so aus:

Code: Alles auswählen

AUTOID   DIST120KPH   DIST150KPH
  0         852          675
  1         987          156
  2         546          285
Ich möchte jetzt die Anzahl der Autos angeben, deren Summe aller Kilometer größer als 1000km ist. Ich hatte es so angedacht:

Code: Alles auswählen

SELECT count(*) FROM (SELECT autoid FROM MeineTabelle WHERE SUM(DIST120KPH + DIST150KPH) >= 1000 GROUP BY autoid)
Eigentlich müsste er mir 2 ausgeben, weil eben 2 Autos insgesamt mehr als 1000km gefahren sind.
Ich bekomme allerdings als Error
misuse of aggregate: sum()
Hat jemand eine Idee, wie man das machen kann?

Gruß Isa
BlackJack

@maria_dolores: `SUM()` und `GROUP BY` weglassen. Was soll das überhaupt erreichen? Wenn eine Auto-ID nicht mehrfach vorkommen kann, macht es nicht viel Sinn danach zu gruppieren und eine Aggregatfunktion zu verwenden. Die würde dann ja sowieso immer nur auf *einen* Datensatz angewendet, was die Aggregation irgendwo sinnlos macht.

Sollte eine Auto-ID in dieser Tabelle doch nicht eindeutig sein, musst Du mit `HAVING` arbeiten. Dort können Aggregatfunktionen verwendet werden.
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

@BlackJack: Vielen Dank. Das hat super geholfen.

Das ist nur ein kleines Beispiel. Meine Datenbank ist nicht ganz so klein. Die IDs der Autos kommen auch öfter vor. Ich halte das Beispiel nur klein, damit man schnell versteht, was ich erreichen möchte. Ich halte nicht so viel davon unendlich langen Code als Beispiel zu posten.

Vielen Dank.
BlackJack

@maria_dolores: Unendlich lange Beispiele sind natürlich nicht so schön, aber das Beispiel sollte halt auch nicht einfacher als das Problem sein, dass Du lösen möchtest, denn sonst besteht die Gefahr, dass Du eine einfache Lösung vorgeschlagen bekommst, die bei Deinem Problem nicht ausreicht.

Speziell bei der Beispieltabelle besteht halt die Gefahr, dass viele bei einer ersten Spalte vom Typ ganze Zahl und mit "ID" im Namen, vermuten werden, dass sei wahrscheinlich der Primärschlüssel. Und dann so Vorschläge machen wie ich, einfach die Aggregation wegzulassen.

Eine weitere Zeile in der Tabelle mit einer AUTOID die doppelt vorkommt, würde in diesem Beispiel ja schon genügen um das Problem genauer darzustellen.
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

@BlackJack: Alles klar. Werde ich berücktsichtigen. Danke.

Bei mir hat sich gerade ein neues Problem ergeben. Vielleicht könnt ihr mir ein weiteres Mal helfen.

Meine aktuelle Tabelle sieht so aus:
Beispiel:

Code: Alles auswählen

AUTOID      ZUSTAND
   0            1
   1            0
   2            1
   3            1
   4            0
   5            1
   6            1
   7            1
   8            1
   9            1
Die Tabelle hat dann insgesamt um die 400 Einträge. Ich möchte nun wissen, wie oft der Zustand 0 im Durchschnitt vorkommt. Mein Ansatz erster Ansatz war, die Funktion avg() zu benutzen, was nicht geklappt hat. Die zweite Idee war, dass ich zwei Selects mache und dann / (teilen) dazwischen schreibe. Funktioniert hat es nicht. War vermutlich zu einfach angedacht.

Code: Alles auswählen

SELECT count(*) from (SELECT zustand from MeineTabelle WHERE zustand == 0) / select count(*) from (select zustand from MeineTabelle)
Im Beispiel sollte dann an sich inhaltlich sowas stehen wie 2/10, sprich 0.2.
Ich hoffe, ihr versteht was ich meine.

Kann mir vielleicht jemand dabei helfen?
BlackJack

@maria_dolores: Falls die Zustände nur 0 und 1 sein könnten, ginge `AVG()` trotzdem:

Code: Alles auswählen

SELECT 1 - AVG(zustand) FROM auto_zustand
Sonst könntest Du zwei Unterabfragen für die beiden Werte verwenden:

Code: Alles auswählen

SELECT 1.0 * a / b
FROM (SELECT count(*) as a FROM auto_zustand WHERE zustand = 0),
     (SELECT count(*) as b FROM auto_zustand)
Die Multiplikation mit 1.0 musste ich da reinbringen, weil SQLite sonst eine Ganzahldivision gemacht hätte, bei der hier ja immer 0 herauskäme.
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Vielen vielen Dank. Du hast mir super weitergeholfen.

Gruß Isa
Antworten