PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : letzte werte mit mysql ermitteln



pido
13-04-2005, 10:00
geht so etwas mit mysql

select teilnr,last(bestand),last(datum) from bestand group by bestand,teilnr

Christoph
13-04-2005, 10:11
"last" ohne ORDER BY macht wohl keinen Sinn. Es gibt in SQL3 LIMIT, vielleicht kennt mySQL das.

pido
13-04-2005, 10:28
das problem liegt wo anders!

bsp:. folgende tab

teilnr | bestand | datum
111 | 500 | 2004-05-03
222 | 34 | 2004-05-03
333 | 1 | 2004-05-03
111 | 300 | 2004-12-22
333 | 210 | 2004-12-22

ergebnis sollte sein

111 | 300 | 2004-12-22
222 | 34 | 2004-05-03
333 | 210 | 2004-12-22

elrond
13-04-2005, 11:35
select ... order by datum desc, teilenr limit 3

das gibt die (chronoligisch) letzten drei DS zurück

Christoph
13-04-2005, 12:53
Aha, jetzt verstehe ich, Du willst in jeder Gruppe das letzte haben. Kein Problem mit GROUP BY und MAX: Aggregatfunktionen werden bei immer nur innerhalb einer Grupee angewandt.

pido
13-04-2005, 13:03
mit max geht es leider nicht !

wenn ich 'select teilnr, bestand, max(datum) from bestand group by teilnr' ausführe

bekomme ich zwar das "letzte" datum aber nicht den dazugehörigen bestand und der ist nicht immer max

Christoph
13-04-2005, 13:43
wenn ich 'select teilnr, bestand, max(datum) from bestand group by teilnr' ausführe

Dafür bräuchtest Du eine correlated Subquery, die MySQL aber -soweit ich weiss- nicht kann. Also sinngemäß:

HAVING datum = (SELECT MAX(datum) FROM bestand WHERE /*Rückbezug zur Gruppe*/).

Hans-Georg Normann
13-04-2005, 20:04
Kannst die Tabelle nicht um einen Autincrement Feld erweitern? Jeder neue Datensatz, bekommt dann eine eindeutige Kennung, Der höchste Wert ist dann auch der letzte.

Hans

pido
14-04-2005, 18:15
wie soll das gehn ?

habe doch das selbe problem wie mit dem datum. ich kann das jüngste datum (mit max) gruppieren, bekomme aber nicht den dazugehörenden bestands wert !!

:confused:

Hans-Georg Normann
14-04-2005, 20:35
wie soll das gehn ?

Gehe doch mal schrittweise vor. Neben deinen bereits vorhanden Spalten teilnr, bestand und datum führen wir lfdnr ein. Dieses Feld erhält einen Zähler, der bei jedem neuen Satz um 1 erhöht wird (Autoincrement). Suchen wir nun die Teilenummer mit der jeweils höchsten laufenden Nummer.
SELECT
TEILNR A_TEILNR,
MAX(LFDNR) A_LFDNR
FROM TAB
GROUP BY TEILNR
ORDER BY TEILNRDas sollte funktionieren und einleuchten, oder? Gehen wir weiter. Wenn ich jetzt die entsprechenden Werte haben möchte, könnte ich das "zu Fuss" so lösen.
SELECT
TEILNR,
BESTAND,
DATUM
FROM TAB
WHERE LFDNR = A_LFDNRA_LFDNR ist durch den ensprechenden Wert aus der ersten Abfrage zu ersetzen. Da LFDNR in deiner Tabelle eindutig (unique) ist, solltest du genau einen Datensatz angezeigt bekommen. Bis hierhin verstanden?

Gehen wir nun den daran, die beiden Abfragen zu verknüpfen.
SELECT
A.TEILNR,
A.BESTAND,
A.DATUM
FROM TAB A
WHERE A.LFDNR IN SELECT
MAX(B.LFDNR)
FROM TAB B
GROUP BY B.TEILNR
ORDER BY TEILNRIch habe das mal eben so zusammengeschrieben. Hoffentlich habe ich nicht zu viele Fehler eingebaut, besonders in der letzten Abfrage. Ich hoffe, dass die folgende Abfrage so gültig ist
SELECT
MAX(B.LFDNR)
FROM TAB B
GROUP BY B.TEILNR
ORDER BY TEILNR

Hans

mwanaheri
15-04-2005, 08:38
Es ist ziemlich umständlich, aber es geht auch mit sehr einfachen Mitteln:
1. erstelle eine view, die nur die Felder teilnr und datum enthält:
create view zwischenview as select teilnr,datum from bestand;

2. filtere daraus den jeweils letzte Eintrag:
create view last as select teilnr, max(datum) as datum from zwischenview group by teilnr;

3. hole dir die kompletten Daten aus der Tabelle:
select bestand.teilnr, bestand.bestand, bestand.datum
from bestand, last
where bestand.teilnr = last.teilnr and bestand.datum = last.datum;

Unter Postgres getestet. Darin dürfte nichts sein, was MySQL nicht kennt.
Voraussetzung ist natürlich, dass es für jedes Datum nur genau einen Eintrag pro teilnr gibt. Ansonsten wäre ein Zeitstempel besser.

Christoph
15-04-2005, 09:37
Den View braucht man nicht unbedingt: ein SELECT Statement in Klammern ist ein Tabellne-Konstruktor. Es geht also z.B. sowas (zumindest mit PostgreSQL):


SELECT name FROM (SELECT * FROM tabelle) x

Das letzte x ist ein Name für die vom Tabellen-Konstruktor generierte tabelle, dan man zumindist in älteren PostgreSQL Versionen immer angeben musste (ab 7.4 kann man ihn glaube ich in manchen Fällen weglassen).

mwanaheri
15-04-2005, 09:48
Den View braucht man nicht unbedingt: ein SELECT Statement in Klammern ist ein Tabellne-Konstruktor. Es geht also z.B. sowas (zumindest mit PostgreSQL):


SELECT name FROM (SELECT * FROM tabelle) x

Das letzte x ist ein Name für die vom Tabellen-Konstruktor generierte tabelle, dan man zumindist in älteren PostgreSQL Versionen immer angeben musste (ab 7.4 kann man ihn glaube ich in manchen Fällen weglassen).

Schon richtig, oben sind ja sogar 2 Views drin (sonst müsste man den Bestand noch verwurschten, z.B. mit sum(bestand)). Ich habe darauf gezielt, die einzelnen Abfragen möglichst einfach zu halten und da schien es mir sinnvoll, einfache Views zu benutzen. Bei tief geschachtelten Abfragen blicke ich selbst immer nicht mehr durch ;-)

noch nicht auf die 8er Version von Postgres umgestieten?

ps: habe es gerade mal durchgespielt:


select test.teilnr, test.datum, test.bestand
from test,( select teilnr,max(datum) as datum from (select teilnr,datum from test) sub1 group by sub1.teilnr) sub2
where test.datum = sub2.datum and test.teilnr = sub2.teilnr;

So etwa sähe es dann aus, oder?