Pergunta

Eu tenho uma tabela MySQL com aproximadamente 3.000 linhas por usuário.Uma das colunas é um campo de data e hora, que é mutável, portanto as linhas não estão em ordem cronológica.

Gostaria de visualizar a distribuição do tempo em um gráfico, por isso preciso de vários pontos de dados individuais.20 pontos de dados seriam suficientes.

Eu poderia fazer isso:

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

e observe cada 150 linhas.

Ou eu poderia fazer 20 consultas separadas e usar limit 1 e offset.

Mas deve haver uma solução mais eficiente...

Foi útil?

Solução

Michal Sznajder quase conseguiu, mas você não pode usar aliases de coluna em uma cláusula WHERE no SQL.Então você tem que envolvê-lo como uma tabela derivada.Eu tentei isso e ele retorna 20 linhas:

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

Outras dicas

Algo assim veio à minha mente

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

Não tenho MySQL em mãos, mas talvez isso ajude ...

No que diz respeito à visualização, sei que esta não é a amostragem periódica da qual você está falando, mas eu examinaria todas as linhas de um usuário e escolheria um intervalo de intervalo, SUM dentro dos intervalos e mostraria em um gráfico de barras ou similar.Isto mostraria uma “distribuição” real, uma vez que muitas ocorrências dentro de um intervalo de tempo podem ser significativas.

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)

Ou se você não gosta da maneira como precisa se repetir - ou se está brincando com diferentes grupos e deseja analisar vários usuários em 3-D (medida em Z contra x, y uid, intervalo):

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 eu quisesse plotar em 3D, provavelmente determinaria uma maneira de ordenar os usuários de acordo com alguma métrica geral significativa para o usuário.

@Michal

Por alguma razão, seu exemplo só funciona quando o where @recnum usa um operador menor que.Acho que quando o where filtra uma linha, o rownum não é incrementado e não pode corresponder a mais nada.

Se a tabela original tiver uma coluna de ID incrementada automaticamente e as linhas forem inseridas em ordem cronológica, isso deverá funcionar:

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

É claro que isso não funciona se não houver correlação entre o id e o campo de tempo, a menos que você realmente não se importe em obter campos de tempo espaçados uniformemente, apenas 20 aleatórios.

Você realmente se preocupa com os pontos de dados individuais?Ou usar as funções estatísticas agregadas no número do dia será suficiente para lhe dizer o que você deseja saber?

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

Não sou especialista em mysql, então não tenho certeza de como Rand() funciona neste ambiente.

Para minha referência - e para aqueles que usam o postgres - o Postgres 9.4 terá agregados de conjuntos ordenados que devem resolver este 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/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top