Frage

Ich habe eine MySQL-Tabelle mit ungefähr 3000 Zeilen pro Benutzer.Eine der Spalten ist ein Datum/Uhrzeit-Feld, das veränderbar ist, sodass die Zeilen nicht in chronologischer Reihenfolge sind.

Ich möchte die Zeitverteilung in einem Diagramm visualisieren und benötige daher eine Reihe einzelner Datenpunkte.20 Datenpunkte würden ausreichen.

Ich könnte Folgendes tun:

select timefield from entries where uid = ? order by timefield;

und schauen Sie sich jede 150. Reihe an.

Oder ich könnte 20 separate Abfragen durchführen und verwenden limit 1 Und offset.

Aber es muss eine effizientere Lösung geben...

War es hilfreich?

Lösung

Michal Sznajder hätte es fast geschafft, aber Sie können in SQL keine Spaltenaliase in einer WHERE-Klausel verwenden.Sie müssen es also als abgeleitete Tabelle umschließen.Ich habe es versucht und es werden 20 Zeilen zurückgegeben:

SELECT * FROM (
    SELECT @rownum:=@rownum+1 AS rownum, e.*
    FROM (SELECT @rownum := 0) r, entries e) AS e2
WHERE uid = ? AND rownum % 150 = 0;

Andere Tipps

So etwas kam mir in den Sinn

select @rownum:=@rownum+1 rownum, entries.* 
from (select @rownum:=0) r, entries 
where uid = ? and rownum % 150 = 0

Ich habe kein MySQL zur Hand, aber vielleicht hilft das ...

Was die Visualisierung angeht, weiß ich, dass es sich nicht um die periodische Stichprobe handelt, von der Sie sprechen, aber ich würde mir alle Zeilen für einen Benutzer ansehen und einen Intervall-Bucket auswählen, SUM innerhalb der Buckets und in einem Balkendiagramm oder ähnlichem anzeigen.Dies würde eine echte „Verteilung“ zeigen, da viele Ereignisse innerhalb eines Zeitrahmens von Bedeutung sein können.

SELECT DATEADD(day, DATEDIFF(day, 0, timefield), 0) AS bucket -- choose an appropriate granularity (days used here)
     ,COUNT(*)
FROM entries
WHERE uid = ?
GROUP BY DATEADD(day, DATEDIFF(day, 0, timefield), 0)
ORDER BY DATEADD(day, DATEDIFF(day, 0, timefield), 0)

Oder wenn Ihnen die Art und Weise, wie Sie sich wiederholen müssen, nicht gefällt – oder wenn Sie mit verschiedenen Buckets spielen und viele Benutzer in 3D analysieren möchten (Messung in Z gegen x, y uid, Bucket):

SELECT uid
    ,bucket
    ,COUNT(*) AS measure
FROM (
    SELECT uid
        ,DATEADD(day, DATEDIFF(day, 0, timefield), 0) AS bucket
    FROM entries
) AS buckets
GROUP BY uid
    ,bucket
ORDER BY uid
    ,bucket

Wenn ich in 3D zeichnen wollte, würde ich wahrscheinlich eine Möglichkeit finden, Benutzer nach einer aussagekräftigen Gesamtmetrik für den Benutzer zu ordnen.

@Michal

Aus irgendeinem Grund funktioniert Ihr Beispiel nur, wenn where @recnum einen Kleiner-als-Operator verwendet.Ich denke, wenn where eine Zeile herausfiltert, wird die Zeilennummer nicht erhöht und kann mit nichts anderem übereinstimmen.

Wenn die Originaltabelle über eine automatisch inkrementierte ID-Spalte verfügt und Zeilen in chronologischer Reihenfolge eingefügt wurden, sollte dies funktionieren:

select timefield from entries
where uid = ? and id % 150 = 0 order by timefield;

Das funktioniert natürlich nicht, wenn keine Korrelation zwischen der ID und dem Zeitfeld besteht, es sei denn, es geht Ihnen eigentlich nicht darum, gleichmäßig verteilte Zeitfelder zu erhalten, sondern nur um 20 zufällige.

Interessieren Sie sich wirklich für die einzelnen Datenpunkte?Oder reicht es stattdessen aus, die statistischen Aggregatfunktionen für die Tageszahl zu verwenden, um Ihnen zu sagen, was Sie wissen möchten?

select timefield
from entries
where rand() = .01 --will return 1% of rows adjust as needed.

Da ich kein MySQL-Experte bin, bin ich mir nicht sicher, wie rand() in dieser Umgebung funktioniert.

Zu meiner Information – und für diejenigen, die Postgres verwenden – Postgres 9.4 verfügt über bestellte Set-Aggregate, die dieses Problem lösen sollten:

SELECT percentile_disc(0.95) 
WITHIN GROUP (ORDER BY response_time) 
FROM pageviews;

Quelle: http://www.craigkerstiens.com/2014/02/02/Examining-PostgreSQL-9.4/

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top