Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]3674[/thread]

SQL-Frage: Groessten Wert fuer jede ID in Tabelle



<< |< 1 2 >| >> 16 Einträge, 2 Seiten
nepos
 2006-04-06 13:29
#34241 #34241
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hallo zusammen!

Ich stehe hier grade ein wenig auf dem Schlauch und vielleicht hat von euch jemand eine Loesung.
Folgendes Problem:
Ich habe eine Tabelle fuer Historie-Daten. Was ich brauche, ist ein SELECT der fuer jede ID in dieser Tabelle den Eintrag zurueckliefert, der den groessten Timestamp hat.
Die Tabelle hat z.B. folgenden Aufbau:
Code: (dl )
1
2
3
4
5
6
7
8
9
CREATE TABLE component_history (
   component_id integer NOT NULL,
   history_timestamp timestamp without time zone DEFAULT '2005-12-29 16:46:13.763751'::timestamp without time zone NOT NULL,
   name character varying NOT NULL,
   fqdn character varying NOT NULL,
   state character varying(10) DEFAULT 'active'::character varying NOT NULL,
   is_byhand boolean DEFAULT false NOT NULL,
   is_measured boolean DEFAULT true NOT NULL
);


Also fuer jede component_id moechte ich, dass ich den Eintrag bekomme, der den groessten history_timestamp hat.
Hat da von euch vielleicht jemand ne Idee?
Danke euch schon mal fuer die Hilfe!

EDIT: Ach ja, die Datenbank ist eine PostgreSQL 7.4.

Gruss,
nepos\n\n

<!--EDIT|nepos|1144324005-->
master
 2006-04-06 15:33
#34242 #34242
User since
2003-10-20
610 Artikel
BenutzerIn
[default_avatar]
Code: (dl )
SELECT* FROM component_history ORDER BY history_timestamp
\n\n

<!--EDIT|master|1144323220-->
$i='re5tsFam ^l\rep';$i=~s/[^a-z| ]//g;$\= reverse "\U!$i";print;
nepos
 2006-04-06 15:46
#34243 #34243
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Ne, das liefert mir nur alle Zeilen sortiert nach dem Timestamp und das aufsteigend.
Mal ein paar Beispieldaten:
Code: (dl )
1
2
3
4
          103 | 2004-09-23 00:00:00 | component01     | component01     | active   | f         | t
         103 | 2006-04-01 00:00:00 | component01     | component01     | inactive | f         | t
         104 | 2004-09-23 00:00:00 | component02     | component02     | active   | f         | t
         104 | 2006-04-01 00:00:00 | component02     | component02     | inactive | f         | t


Was ich brauche, ist eine Abfrage, die bei diesem Beispiel nur folgende 2 Datensaetze zurueckliefert:
Code: (dl )
1
2
          103 | 2006-04-01 00:00:00 | component01     | component01     | inactive | f         | t
         104 | 2006-04-01 00:00:00 | component02     | component02     | inactive | f         | t
renee
 2006-04-06 15:59
#34244 #34244
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
[sql]SELECT * FROM table GROUP BY id ORDER BY timestamp DESC[/sql]
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
nepos
 2006-04-06 16:08
#34245 #34245
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Ne, das geht leider auch nicht :-\
Soweit war ich auch schon, nur ist das Problem, dass man alle Felder so in den GROUP BY stecken muss. Das macht dann natuerlich wieder keinen Sinn mehr...
master
 2006-04-06 16:35
#34246 #34246
User since
2003-10-20
610 Artikel
BenutzerIn
[default_avatar]
Code: (dl )
SELECT LIMIT 2 * FROM component_history ORDER BY history_timestamp (LIMIT 2 )



Ist glaub LIMIT damit kannst du es begrenzen so werden nur 2 ausgelesen (weiss nicht mehr ob limit am anfang oder schluss stehen muss...)

aber solange es den Timestamp nicht richtig sortiert hilfts nicht...
gibt noch spezielle MySQL befehle für Date usw.

Speicher sonst die Daten besser getrennt(2 Felder) :
date + time
------
oder mach nen timestamp als int... also so : 100234324230

diese all-inclusive-timestamps machen eh immer mühe..
und meist willst du eh unr z.b. das datum, oder dann mit zeit.
uhrzeit und datum würde ich trennen.\n\n

<!--EDIT|master|1144326976-->
$i='re5tsFam ^l\rep';$i=~s/[^a-z| ]//g;$\= reverse "\U!$i";print;
roli
 2006-04-06 16:40
#34247 #34247
User since
2004-12-31
424 Artikel
BenutzerIn
[default_avatar]
Hi,

wenn's noch moeglich ist, wuerde ich die Tabellendefinition veraendern.
Mach doch aus dem Feld "history_timestamp" einen Integer, in dem du die Zeit im Epoch Format, also den Sekunden seit dem 1.1.1970 ablegst. Dann ist der Vergleich, auch in Scripten, einfacher.
Funktioniert vielleicht folgende SQL:
Code: (dl )
1
2
SELECT *, MAX(history_timestamp) FROM component_history
GROUP BY id

Ist aber nicht getestet.
Roland
--
"Steh vorn, während du fragst;
sitzen soll, wer antwortet."
Aus "Die Edda des Snorri Sturluson" "Gylfis Täuschung" Strophe 2
master
 2006-04-06 16:45
#34248 #34248
User since
2003-10-20
610 Artikel
BenutzerIn
[default_avatar]
@roli

int würde ich nicht machen bzw. nur im notfall (speedgründe)

int = 2000 problem

ist ja ab 1999 irgendwann gerechnet.. und da kommt man irgendwann an ein limit..

besser ein date-feld und ein time-feld.
im date steht dann "2006-04-01" und das gibt nie probleme

zudem kann man dann mit den date-funktionen von MySql arbeiten bei den abfragen.
$i='re5tsFam ^l\rep';$i=~s/[^a-z| ]//g;$\= reverse "\U!$i";print;
nepos
 2006-04-06 16:56
#34249 #34249
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Ob das nun ein Date oder ein Integer oder was weiss ich ist, das macht keinen Unterschied.
@Master: Limit hilft auch nix, weil ich das Maximum ja pro ID haben will... Mit deinem Ansatz krieg ich einfach alles, mit Limit dann halt nur einen Datensatz. Ich brauch aber genau den einen fuer jede ID.

@roli: Im Prinzip das gleiche Problem wie bei renee's Ansatz: ich muesste dann alle anderen Felder ausser den Timestamp in die GROUP BY-Klausel einbauen. Damit werden dann aber 2 Datensaetze nich als gleich betrachtet, wenn sich z.B. der ame Name geaendert hat...

Scheint irgendwie doch nicht so trivial zu sein mein Problem :(

Vom Logischen her braeucht ich eben sowas:
Fuer jede eindeutige ID in der Tabelle suche die Zeile mit groesstem Timestamp und gib sie zurueck.
master
 2006-04-06 17:11
#34250 #34250
User since
2003-10-20
610 Artikel
BenutzerIn
[default_avatar]
Stichwort: "subselect" Das hilft dir aus der Klemme
Mit subselects geht sowas immer
(code ev. nicht ganz korrekt):

Code: (dl )
1
2
3
4
SELECT  * FROM component_history WHERE ID =
(
SELECT DISTINCT LIMIT 1 ID FROM component_history ORDER BY history_timestamp WHERE ID=component_history.ID
)



DISTINCT = MSSQL  (ev. auch so in MySQL und sonst musst du nachsehen)

So wird jedenfalls für Jede ID immer der datensatz mit dem höchsten Timestamp genommen


Das Was in Klammern ist wird dann autmatisch durch die aktuelle ID ersetzt.\n\n

<!--EDIT|master|1144329365-->
$i='re5tsFam ^l\rep';$i=~s/[^a-z| ]//g;$\= reverse "\U!$i";print;
<< |< 1 2 >| >> 16 Einträge, 2 Seiten



View all threads created 2006-04-06 13:29.