Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > de.comp.lang.php > #4105 > unrolled thread
| Started by | Sebastian Suchanek <sebastian.suchanek@gmx.de> |
|---|---|
| First post | 2017-05-15 22:53 +0200 |
| Last post | 2017-05-18 22:03 +0200 |
| Articles | 4 — 3 participants |
Back to article view | Back to de.comp.lang.php
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Zeitabhängige Gruppierung von Datensätzen Sebastian Suchanek <sebastian.suchanek@gmx.de> - 2017-05-15 22:53 +0200
Re: Zeitabhängige Gruppierung von Datensätzen Stefan+Usenet@Froehlich.Priv.at (Stefan Froehlich) - 2017-05-15 21:03 +0000
Re: Zeitabhängige Gruppierung von Datensätzen Axel Schwenke <axel.schwenke@gmx.de> - 2017-05-16 15:27 +0200
Re: Zeitabhängige Gruppierung von Datensätzen Sebastian Suchanek <sebastian.suchanek@gmx.de> - 2017-05-18 22:03 +0200
| From | Sebastian Suchanek <sebastian.suchanek@gmx.de> |
|---|---|
| Date | 2017-05-15 22:53 +0200 |
| Subject | Re: Zeitabhängige Gruppierung von Datensätzen |
| Message-ID | <ofd4fr$kk1$1@msgid.suchanek.de> |
Am 24.04.2017 um 14:09 schrieb Axel Schwenke: > On 22.04.2017 20:24, Sebastian Suchanek wrote: Ich pack's mal in diesen Thread, damit Interessierte den Hintergrund kennen. >> Für ein elektronisches Fahrtenbuch[1] habe ich eine Tabelle, die unter >> anderem die Felder "start_zeit", "start_km", "ende_zeit" und "ende_km" >> enthält, wo bei in den beiden "km"-Feldern die absoluten Kilometerstände >> des Autos bei Anfang und Ende der Fahrt gespeichert werden. > >> Was ich nun gerne optional hätte, ist folgendes Ergebnis (hier am >> Beispiel Fahrten, die nicht länger als 30min auseinander liegen, >> zusammenfassen): > >> Gibt's einen Weg, das innerhalb von MySQL zu lösen? > > Klar. > [...] > Wir bauen uns als erstes eine synthetische Spalte tour_id, die Touren > zusammenfaßt, die nicht weiter als 30 Minuten auseinander liegen. Dazu > brauchen wir zwei User-Variablen für die id und die Anfangszeit: > > MariaDB [test]> set @tour_id=0; > [...] > MariaDB [test]> select @ts:=min(t2) from fahrten; > [...] > Jetzt können wir dieses Ergebnis in einer derived table Subquery benutzen: > > MariaDB [test]> select min(start) as start, max(ende) as ende, sum(weg) from > (select @tour_id:=if(@ts + interval 30 minute > t1, @tour_id, @tour_id+1) as > tour_id, t1 as start, @ts:=t2 as ende, s2-s1 as weg from fahrten order by > t1) as temp1 group by tour_id; > [...] Inzwischen bin ich endlich mal dazu gekommen, das o.g. tatsächlich zu implementieren - bzw., ich habe es versucht. Hier zunächst "meine" Query. Die Spaltennamen sind an meine eigene Tabelle angepasst und lasse mir das Ergebnis in eine temporäre Tabelle packen, da ich damit die für mich eigentlich interessanten statistischen Auswertungen leichter machen kann: ------------------------------------- 8< ------------------------------ SET @tour_id=0; SELECT @ts:=min(ende_zeit) FROM Fahrten; CREATE TEMPORARY TABLE IF NOT EXISTS tours AS (SELECT MIN(start) AS `start`, MAX(ende) AS `ende`, SUM(weg) AS `weg` FROM (SELECT @tour_id:=IF(@ts + INTERVAL 30 MINUTE > start_zeit, @tour_id, @tour_id+1) AS `tour_id`, start_zeit AS `start`, @ts:=ende_zeit AS `ende`, ende_km-start_km AS `weg` FROM Fahrten ORDER BY start_zeit) AS temp1 GROUP BY tour_id); SELECT * FROM tours; ------------------------------------- 8< ------------------------------ Wenn ich diese Statements z.B. unter PHPmyAdmin in die "SQL"-Eingabe einkippe, erhalte ich das gewünschte Ergebnis. Wenn ich sie stattdessen in meinem eigenen Skript mittels mysqli::query ausführen will, erhalte stattdessen aber eine Fehlermeldung: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT @ts:=min(ende_zeit) FROM Fahrten; CREATE TEMPORARY TABLE IF NOT EXISTS to' at line 1" Wahrscheinlich hängt's nur an einer Kleinigkeit, trotzdem stehe ich gerade auf dem Schlauch. Kann mir 'mal jemand von dort 'runterhelfen? ;-) Was ich einigermaßen sicher ausschließen kann: - Tippfehler. Ich habe mir den Query-String aus meinem eigenen Skript ausgeben lassen und per Copy&Paste sowohl in PHPmyAdmin als auch in dieses Posting kopiert. (Zur minimal besseren Lesbarkeit habe ich hier im Posting nur ein paar Zeilenumbrüche eingefügt.) - Fehlende Zugriffsrechte. Erstens hat der DB-Nutzer, mit dem das Skript läuft, für die fragliche Datenbank "ALL PRIVILEGES"; zweitens tritt der Fehler auch dann auf, wenn ich das Skript testweise mit dem DB-root-Nutzer laufen lasse; und drittens würde ich da eine andere Fehlermeldung erwarten. Wie gesagt: wo liegt der Fehler? Da ich das Problem eher bei PHP (BTW: v5.6.30 "out of the box" auf Debian Jessie) vermute, mache ich mal ein XP nach de.comp.lang.php. Vorläufig ohne f'up, bitte beim Antworten entsprechend setzen. Tschüs, Sebastian
[toc] | [next] | [standalone]
| From | Stefan+Usenet@Froehlich.Priv.at (Stefan Froehlich) |
|---|---|
| Date | 2017-05-15 21:03 +0000 |
| Message-ID | <enujc6Fb328U1@mid.individual.net> |
| In reply to | #4105 |
In de.comp.lang.php Sebastian Suchanek <sebastian.suchanek@gmx.de> wrote: > ------------------------------------- 8< ------------------------------ > SET @tour_id=0; > SELECT @ts:=min(ende_zeit) FROM Fahrten; > CREATE TEMPORARY TABLE IF NOT EXISTS tours AS (SELECT MIN(start) AS > `start`, MAX(ende) AS `ende`, SUM(weg) AS `weg` FROM (SELECT > @tour_id:=IF(@ts + INTERVAL 30 MINUTE > start_zeit, @tour_id, > @tour_id+1) AS `tour_id`, start_zeit AS `start`, @ts:=ende_zeit AS > `ende`, ende_km-start_km AS `weg` FROM Fahrten ORDER BY start_zeit) AS > temp1 GROUP BY tour_id); > SELECT * FROM tours; > ------------------------------------- 8< ------------------------------ > > Wenn ich diese Statements z.B. unter PHPmyAdmin in die "SQL"-Eingabe > einkippe, erhalte ich das gewünschte Ergebnis. > Wenn ich sie stattdessen in meinem eigenen Skript mittels mysqli::query > ausführen will, erhalte stattdessen aber eine Fehlermeldung: > "You have an error in your SQL syntax; check the manual that corresponds > to your MySQL server version for the right syntax to use near 'SELECT > @ts:=min(ende_zeit) FROM Fahrten; CREATE TEMPORARY TABLE IF NOT EXISTS > to' at line 1" > Wahrscheinlich hängt's nur an einer Kleinigkeit, [...] "Kleinigkeit" ist relativ, aber es ist einfach zu beheben. Vereinfacht gesagt liegt das Problem beim Strichpunkt (deshalb auch "near SELECT @ts""), Du brauchst einen eigenen Befehl, um mehrere Statements in einem query-Statement ausführen zu können: <http://php.net/manual/de/mysqli.quickstart.multiple-statement.php> Servus, Stefan -- http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich Offizieller Erstbesucher(TM) von mmeike Endlich ein imaginärer Gedanke: Stefan! (Sloganizer)
[toc] | [prev] | [next] | [standalone]
| From | Axel Schwenke <axel.schwenke@gmx.de> |
|---|---|
| Date | 2017-05-16 15:27 +0200 |
| Message-ID | <ofeuhm$2ke$1@dont-email.me> |
| In reply to | #4106 |
On 15.05.2017 23:03, Stefan Froehlich wrote: > In de.comp.lang.php Sebastian Suchanek <sebastian.suchanek@gmx.de> wrote: [4 separate SQL Statements] >> Wenn ich diese Statements z.B. unter PHPmyAdmin in die "SQL"-Eingabe >> einkippe, erhalte ich das gewünschte Ergebnis. >> Wenn ich sie stattdessen in meinem eigenen Skript mittels mysqli::query >> ausführen will, erhalte stattdessen aber eine Fehlermeldung [snip] >> Wahrscheinlich hängt's nur an einer Kleinigkeit, [...] > > "Kleinigkeit" ist relativ, aber es ist einfach zu beheben. > Vereinfacht gesagt liegt das Problem beim Strichpunkt (deshalb auch > "near SELECT @ts""), Du brauchst einen eigenen Befehl, um mehrere > Statements in einem query-Statement ausführen zu können: > <http://php.net/manual/de/mysqli.quickstart.multiple-statement.php> Hmm. Damit hatte ich ehrlich gesagt nicht gerechnet, daß Sebastian versuchen würde, mehrere Statements in einem Rutsch auszuführen. Das geht zwar in phpMyAdmin und im MySQL CLI, aber nur deswegen, weil diese Tools ihre Eingabe parsen und an den ";" in Teile zerschneiden, die sie dann nacheinander an den Server schicken. Meine Empfehlung wäre, eben diesen Weg zu gehen: für jedes der 4 Statements einmal mysqli::query aufrufen. Und zwar natürlich für das gleiche mysqli Objekt, weil die User-Variablen und die temporäre Tabelle ja spezifisch für die MySQL-Connection sind. Die Unterstützung für multi-statements ist normalerweise ausgeschaltet. Und das ist auch gut so. Man kann eine ganze Klasse von SQL-Injection Angriffen ausschalten, indem man multi-statements verbietet.
[toc] | [prev] | [next] | [standalone]
| From | Sebastian Suchanek <sebastian.suchanek@gmx.de> |
|---|---|
| Date | 2017-05-18 22:03 +0200 |
| Message-ID | <ofkumt$13r$1@msgid.suchanek.de> |
| In reply to | #4107 |
Am 16.05.2017 um 15:27 schrieb Axel Schwenke:
> On 15.05.2017 23:03, Stefan Froehlich wrote:
>> In de.comp.lang.php Sebastian Suchanek <sebastian.suchanek@gmx.de> wrote:
>
> [4 separate SQL Statements]
>
>>> Wenn ich diese Statements z.B. unter PHPmyAdmin in die "SQL"-Eingabe
>>> einkippe, erhalte ich das gewünschte Ergebnis.
>>> Wenn ich sie stattdessen in meinem eigenen Skript mittels mysqli::query
>>> ausführen will, erhalte stattdessen aber eine Fehlermeldung
>
> [snip]
>
>>> Wahrscheinlich hängt's nur an einer Kleinigkeit, [...]
>>
>> "Kleinigkeit" ist relativ, aber es ist einfach zu beheben.
>> Vereinfacht gesagt liegt das Problem beim Strichpunkt (deshalb auch
>> "near SELECT @ts""), Du brauchst einen eigenen Befehl, um mehrere
>> Statements in einem query-Statement ausführen zu können:
>> <http://php.net/manual/de/mysqli.quickstart.multiple-statement.php>
>
> Hmm. Damit hatte ich ehrlich gesagt nicht gerechnet, daß Sebastian versuchen
> würde, mehrere Statements in einem Rutsch auszuführen.
Ich war fälschlicherweise davon ausgegangen, dass nach jedem Aufruf von
mysqli::query die Verbindung zur Datenbank implizit beendet würde, womit
dann z.B. auch temporäre Tabellen perdu wären. Inzwischen weiß ich, dass
dem nicht so ist.
(Erscheint rückblickend auch logischer... :-))
> [...]
> Meine Empfehlung wäre, eben diesen Weg zu gehen: für jedes der 4 Statements
> einmal mysqli::query aufrufen. Und zwar natürlich für das gleiche mysqli
> Objekt, weil die User-Variablen und die temporäre Tabelle ja spezifisch für
> die MySQL-Connection sind.
So habe ich das inzwischen gemacht, ja. Aber hauptsächlich deswegen,
weil ich dabei das anschließende Handling des/der Ergebnisse(s)
persönlich einfacher finde.
> Die Unterstützung für multi-statements ist normalerweise ausgeschaltet. Und
> das ist auch gut so. Man kann eine ganze Klasse von SQL-Injection Angriffen
> ausschalten, indem man multi-statements verbietet.
Das nimmt man natürlich gerne mit. So gesehen frage mich dann aber
schon, wo der Vorteil von mysqli::multi_query gegenüber ein paar
nacheinander ausgeführten mysqli::query ist.
Tschüs,
Sebastian
PS: f'up2 dclp, weil das mit MySQL im engeren Sinn nicht mehr viel zu
tun hat.
[toc] | [prev] | [standalone]
Back to top | Article view | de.comp.lang.php
csiph-web