Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.comp.lang.php > #4105 > unrolled thread

Re: Zeitabhängige Gruppierung von Datensätzen

Started bySebastian Suchanek <sebastian.suchanek@gmx.de>
First post2017-05-15 22:53 +0200
Last post2017-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.


Contents

  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

#4105 — Re: Zeitabhängige Gruppierung von Datensätzen

FromSebastian Suchanek <sebastian.suchanek@gmx.de>
Date2017-05-15 22:53 +0200
SubjectRe: 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]


#4106

FromStefan+Usenet@Froehlich.Priv.at (Stefan Froehlich)
Date2017-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]


#4107

FromAxel Schwenke <axel.schwenke@gmx.de>
Date2017-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]


#4108

FromSebastian Suchanek <sebastian.suchanek@gmx.de>
Date2017-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