Вопрос

У меня есть таблица MySQL примерно с 3000 строками на пользователя.Один из столбцов представляет собой поле даты и времени, которое изменяемо, поэтому строки расположены не в хронологическом порядке.

Я хотел бы визуализировать распределение времени на графике, поэтому мне нужно несколько отдельных точек данных.20 точек данных было бы достаточно.

Я мог бы это сделать:

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

и посмотрите на каждый 150-й ряд.

Или я мог бы выполнить 20 отдельных запросов и использовать limit 1 и offset.

Но должно быть более эффективное решение...

Это было полезно?

Решение

Михал Шнайдер почти добился этого, но вы не можете использовать псевдонимы столбцов в предложении WHERE в SQL.Таким образом, вы должны обернуть его в виде производной таблицы.Я попробовал это, и это возвращает 20 строк:

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

Другие советы

Что-то вроде этого пришло мне в голову

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

У меня нет MySQL под рукой, но, возможно, это поможет...

Что касается визуализации, я знаю, что это не периодическая выборка, о которой вы говорите, но я бы посмотрел на все строки для пользователя и выбрал интервал, СУММИРОВАЛ внутри сегментов и показал на гистограмме или подобном.Это показало бы реальное "распределение", поскольку многие события в течение определенного периода времени могут быть значительными.

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)

Или если вам не нравится, что вам приходится повторяться, или если вы играете с разными сегментами и хотите проанализировать работу многих пользователей в трехмерном режиме (измерьте в Z по сравнению с 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

Если бы я хотел построить график в 3D, я бы, вероятно, определил способ упорядочивания пользователей в соответствии с каким-то значимым общим показателем для пользователя.

@Михал

По какой-то причине ваш пример работает только тогда, когда where @recnum использует оператор less than.Я думаю, когда where отфильтровывает строку, число строк не увеличивается, и оно не может соответствовать чему-либо еще.

Если исходная таблица имеет автоматически увеличиваемый столбец id, а строки были вставлены в хронологическом порядке, то это должно сработать:

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

Конечно, это не сработает, если нет корреляции между идентификатором и временным полем, если только вы на самом деле не заботитесь о получении равномерно расположенных временных полей, всего 20 случайных.

Вас действительно волнуют отдельные точки данных?Или вместо этого будет достаточно использовать статистические агрегированные функции для определения номера дня, чтобы сообщить вам то, что вы хотите знать?

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

Не эксперт по mysql, поэтому я не уверен, как rand () работает в этой среде.

Для моей справки - и для тех, кто использует postgres - Postgres 9.4 будет иметь упорядоченные агрегированные наборы, которые должны решить эту проблему:

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

Источник: http://www.craigkerstiens.com/2014/02/02/Examining-PostgreSQL-9.4/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top