MySQL Problem

Hallo zusammen,

eine Frage an die SQL-Experten:

ich versuche gerade einige Werte aus einer extern gelagerten Datenbank abzufragen und diese in IPS zu visualisieren. Grundsätzlich funktioniert das aber ein logisches Problem habe ich noch.

Zur Erklärung:
Die Tabelle ist schematisch so aufgebaut:
ID–Quelle–Wert
In unbestimmten Abständen werden diese Werte angehängt, also sieht die Tabelle so aus:
ID–Quelle–Wert
1–10–5
2–6--3
3–8--5
4–10–6
5–10–7
6–6--7

Jetzt hatte ich gerne mit einer zyklischen Abfrage zu jeder Quelle den aktuellsten Wert , also
5–10–7
6–6--7
3–8--5

Wie kann ich das in MySQL hinbekommen. Ich hatte es mir „order by“ und „limit“ probiert, hat aber leider nicht zum Erfolg geführt

Danke für Eure Hilfe!
Gruß
spooniester

Sehr einfach und auch der das ganze übersichtlicher zu machen , würde ich ein timestamp mit in die Datenbank schreiben. Damit lässt sich die Abfrage sehr einfach gestalten . Falls das nicht für dich Frage kommt , melde dich nochmal.

Hi,

danke erstaml für deine Antwort.
Timestamp wäre kein Problem, jedoch kommen die Daten nicht in gleichen Abständen, die Tabelle sieht also so aus:

---ID----Quelle--Wert---Starttime---------------Endtime-----------
| 752 |      2 |   27.2 | 2012-11-02 14:00:08 | 2012-11-02 14:01:08 |
| 753 |     14 |   18.7 | 2012-11-02 14:00:20 | 2012-11-02 14:02:21 |
| 754 |      2 |   26.2 | 2012-11-02 14:01:08 | 2012-11-02 14:02:08 |
| 755 |     10 |   24.5 | 2012-11-02 14:01:08 | 2012-11-02 14:03:08 |
| 756 |      2 |   25.6 | 2012-11-02 14:02:08 | 2012-11-02 14:03:08 |
| 757 |     14 |   18.6 | 2012-11-02 14:02:21 | 2012-11-02 14:03:21 |
| 758 |      2 |   25.3 | 2012-11-02 14:03:08 | 2012-11-02 14:04:17 |
| 759 |     10 |   24.7 | 2012-11-02 14:03:08 | 2012-11-02 14:04:17 |
| 760 |     14 |   18.5 | 2012-11-02 14:03:21 | 2012-11-02 14:06:22 |
| 761 |      2 |   25.1 | 2012-11-02 14:04:17 | 2012-11-02 14:05:17 |
| 762 |     10 |   24.5 | 2012-11-02 14:04:17 | 2012-11-02 14:09:26 |
| 763 |      4 |   49.7 | 2012-11-02 14:04:27 | 2012-11-02 14:08:37 |
| 764 |      2 |   24.9 | 2012-11-02 14:05:17 | 2012-11-02 14:06:17 |
| 765 |      2 |   24.8 | 2012-11-02 14:06:17 | 2012-11-02 14:08:17 |
| 766 |     14 |   18.4 | 2012-11-02 14:06:22 | 2012-11-02 14:09:23 |
| 767 |      5 |     30 | 2012-11-02 14:06:22 | 2012-11-02 14:09:23 |
| 768 |      1 |     30 | 2012-11-02 14:07:17 | 2012-11-02 14:09:26 |
| 769 |      2 |   24.7 | 2012-11-02 14:08:17 | 2012-11-02 14:09:26 |

Ich hätte gerne beispielsweise für die Quelle 14 den Wert 18.4 ausgegeben!

Gruß
spooniester

GROUP BY wäre eine der Möglichkeiten:


SELECT * FROM <<Table>> where ID in (select max(ID) from <<Table>> group by Quelle);

Hi Brownson,

funktioniert, danke schonmal.
Allerdings dauert es ewig, obwohl die DB recht klein ist.

19 rows in set (19.33 sec)

Lässt sich das beschleunigen?

Gruß
spooniester

Kommt auf deine Datenbankstruktur an.

Wenn du Indizes auf die notwendigen Felder legst, könnte es helfen.

Letztendlich würde ich Dir hier eine Aufteilung in „aktuelle Daten“ und „History Daten“ empfehlen.

In der akutellen Tabelle jeweils nur der letzte Datensatz und bei jedem Update auch einen Eintrag in der History Tabelle machen!

sollte das nicht ein einfacher group sein?

SELECT QUELLE, LAST(WERT) FROM TABLE GROUP BY QUELLE?

bin mir nicht sicher ob es den LAST beim MySql auch gibt oder ob der nur bei MSSQL geht.

sonst würde ich mit einer TEMP-Table arbeiten

CREATE TEMP TABLE IDS (ID);
INSERT INTO IDS SELECT max(ID) FROM TABELLE GROUP BY QUELLE;
SELECT * FROM TABELLE INNER JOIN IDS ON TABELLE.ID=IDS.ID;

eine Timestamp spalte mit default now() anhängen und mit max(timestamp) für immer ruhe haben.

so habe ich bei meinen Tabellen gelöst.

@PICS: Geil, der Hinweis mit Last war richtig, hier das Ergebnis:

SELECT * FROM <<Table>> where ID in (select max(ID) from <<Table>> group by Quelle);
19 rows in set (22.19 sec)

dagegen

select quelle, LAST_insert_id(wert) from <<Table>> group by quelle;
19 rows in set (0.02 sec)


@All: Danke für Eure Hife, aber mit 0.02 Sekunden kann ich leben :smiley:

Gruß
spooniester

Mist, zu früh gefreut, geht doch nicht so, irgenwie zeigt er mir alte Daten an! Also, muss ich mir doch die anderen Vorschläge mal zu Gemüte führen.
Ich meld mich ggfs. nochmal wenn ich nicht weiterkomme!

Danke trotzdem an alle!

Gruß
spooniester

naja, die last-insert-id war wohl nicht richtig.

mein ansatz wäre eben die letzte (=höchste) ID je quelle in eine Zwischentabelle zu schicken und das ganze dann mit JOIN zu lösen.

ginge aber auch so, aber vermutlich langsamer

SELECT * FROM TABLE
WHERE ID IN (SELECT max(ID) FROM TABELLE GROUP BY QUELLE);

Hi,
ja, ist deutlich langsamer, braucht bei relativ kleinen Tabelle schon 40Sekunden. Das Problem ist das die Daten von einem Collector in die DB geschrieben werden. Diesen Collector hat jemand anderes in C programmiert, für mich leider böhmische Dörfer!

Also, weitere Vorschläge sind Willkommen!

Gruß
spooniester

ja, drum eben den weg mit der temporären Tabelle, das sollte die 40s auf 1s beschleunigen.

Hi,
ok, aber muss ich Tabelle dann bei jeder Abfrage von IPS aus erstellen und so Abfragen wir du beschrieben hast?

Gruß
spooniester

hier ein echtes Beispiel aus PHP-Code, die temp-table gilt nur für den einen Aufruf

hier ein Beispiel der php-befehle

mysql_execute(„CREATE TEMPORARY TABLE TMP_LOOKUP (id INT) ENGINE = MEMORY;“);
mysql_execute(„INSERT INTO TMP_LOOKUP SELECT DISTINCT SELECT max(ID) FROM TABELLE GROUP BY QUELLE;“);

und dann den eigentlichen Query
SELECT * FROM TABELLE INNER JOIN IDS ON TABELLE.ID=TMP_LOOKUP.id;

die ersten beiden Befehle erstellen die Temp-Tabelle und befüllen Sie mit der höchsten ID je quelle
der query dank INNER JOIN sollte dann schnell sein

Hi,

das scheint nicht zu funktionieren???

Gruß
spooniester

Was funktioniert nicht?
Welcher Fehler kommt?

hast den SQL angepasst, was unterstützt dein mysql alles?

theoretische Bugsuche ist noch schwieriger als theoretische Programmierung.

Hi,

Sorry, hast recht.
Er meldet fehlerhafte Syntax. MySQL Server läuft auf debian Version 5.5

Den Rest kann ich morgen früh erst liefern, aber vielleicht reicht das ja schon!

Gruß

Versuchs mal so:


mysql_execute("INSERT INTO TMP_LOOKUP SELECT max(ID) FROM TABELLE GROUP BY QUELLE;");

aber wie bereits geschrieben, ich würde mir einen Tabellen Trigger anlegen und dort eine 2. Tabelle befüllen, wo nur mehr die aktuellsten Werte drinnen stehen.