Domanda

Ho una tabella MySQL con circa 3000 righe per utente.Una delle colonne è un campo data/ora, che è modificabile, quindi le righe non sono in ordine cronologico.

Mi piacerebbe visualizzare la distribuzione temporale in un grafico, quindi ho bisogno di una serie di punti dati individuali.20 punti dati sarebbero sufficienti.

Potrei fare questo:

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

e guarda ogni 150a riga.

Oppure potrei fare 20 query separate e utilizzare limit 1 E offset.

Ma ci deve essere una soluzione più efficiente...

È stato utile?

Soluzione

Michal Sznajder ce l'aveva quasi fatta, ma non è possibile utilizzare alias di colonna in una clausola WHERE in SQL.Quindi devi racchiuderlo come una tabella derivata.Ho provato questo e restituisce 20 righe:

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

Altri suggerimenti

Mi è venuta in mente una cosa del genere

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

Non ho MySQL a portata di mano ma forse questo aiuterà ...

Per quanto riguarda la visualizzazione, so che questo non è il campionamento periodico di cui stai parlando, ma guarderei tutte le righe per un utente e sceglierei un intervallo di intervalli, SOMMA all'interno dei intervalli e lo mostrerei su un grafico a barre o simile.Ciò mostrerebbe una vera e propria "distribuzione", poiché molti eventi in un arco di tempo potrebbero essere significativi.

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)

Oppure se non ti piace il modo in cui devi ripeterti - o se stai giocando con contenitori diversi e desideri analizzare molti utenti in 3-D (misura in Z rispetto a x, y uid, contenitore):

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

Se volessi tracciare in 3-D, probabilmente determinerei un modo per ordinare gli utenti in base a una metrica complessiva significativa per l'utente.

@Michal

Per qualsiasi motivo, il tuo esempio funziona solo quando where @recnum utilizza un operatore minore di.Penso che quando dove filtra una riga, il rownum non viene incrementato e non può corrispondere a nient'altro.

Se la tabella originale ha una colonna ID incrementata automaticamente e le righe sono state inserite in ordine cronologico, dovrebbe funzionare:

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

Ovviamente questo non funziona se non c'è correlazione tra l'id e il campo temporale, a meno che non ti interessi effettivamente ottenere campi temporali equidistanti, solo 20 casuali.

Ti interessano davvero i singoli punti dati?Oppure basterà invece utilizzare le funzioni di aggregazione statistica sul numero del giorno per dirti cosa desideri sapere?

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

Non sono un esperto di MySQL, quindi non sono sicuro di come funzioni Rand() in questo ambiente.

Per mio riferimento - e per coloro che utilizzano Postgres - Postgres 9.4 avrà ordinato set di aggregati che dovrebbero risolvere questo problema:

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

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top