MySQL: ограничить результаты вычисленным шагом - PullRequest
1 голос
/ 07 июня 2011

У меня есть необходимость возвращать определенное количество строк из запроса в течение заданного времени начала и окончания с динамически вычисляемым интервалом шага.

Здесь я упростил задачу с таблицей, состоящей изметка времени unix и соответствующее целочисленное значение.

В моем примере мне нужно иметь 200 строк, возвращаемых с ИНКЛЮЗИВНЫМ временем начала 1307455099 и и ИНКЛЮЗИВНЫМ временем окончанияиз 1307462455 .

Вот текущий запрос, который я разработал до сих пор.Он использует модуль общего количества строк для вычисления шага шага:

SELECT timestamp, value FROM soh_data
WHERE timestamp % (CAST((1307462455 - 1307455099)/200 AS SIGNED INTEGER)) = 0
AND timestamp BETWEEN 1307455099 AND 1307462455 
ORDER BY timestamp;

Первая проблема заключается в том, что, поскольку я использую модуль, время начала и окончания не всегда включено (это можно решить с помощьюдополнительный запрос ... я в порядке).

Второй, более трудный вопрос, который нужно решить, это то, что общее количество строк, возвращаемых в этом случае, составляет только 196. В большинстве запросов это n-1.

К вашему сведению, это база данных MySQL с миллионами строк данных.

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 08 июня 2011

Так как я могу выбросить несколько строк, но я не в порядке, имея слишком мало данных, я предложил два разных подхода.

Первое: я решил адаптироватьсямой запрос использовать FLOOR вместо CAST.В моем примере коэффициент деления был 21.805.SQL округлил это до 22. Правильный интервал шага для сбора более 200 результатов был 21 (получив 205 результатов).Использование FLOOR даст мне номер шага 21, который мне нужен.К сожалению, я не полностью проверил это, чтобы обеспечить согласованные результаты для больших наборов:

SELECT DISTINCT timestamp FROM soh_data 
WHERE timestamp % (FLOOR((1307459460 - 1307455099)/200)) = 0 
AND timestamp BETWEEN 1307455099 AND 1307459460 
ORDER BY timestamp;

Более надежным решением является предварительный расчет шага в коде.Таким образом, я могу сосредоточиться на шаге программно.В следующем примере я использую Ruby для удобства чтения, но мое окончательное решение будет написано на C ++:

lower = 1307455099
upper = 1307459460

limit = 200
range = lower..upper
matches = 0
stepFactor = ((upper-1) - (lower+1))/limit

while (matches <= (limit - 2)) do
    matches = 0

    range.each { |ts| matches += 1 if (ts % stepFactor == 0) }

    stepFactor -= 1 # For the next attempt

    puts "Step factor = #{stepFactor+1}"
    puts "Matches = #{matches}"
end
0 голосов
/ 07 июня 2011

Количество возвращаемых строк будет полностью зависеть от того, сколько временных меток соответствует вашему условию, конечно.Допустим, значение вашего шага составляет 2, поэтому по модулю математика сводится к «только четным временным меткам».Если случайно все элементы в вашей таблице имеют нечетные временные метки, то вы получите 0 возвращенных строк, даже если есть (скажем) 500+ элементов в пределах временного диапазона.

Если вам нужно ровно 200,вам, вероятно, будет лучше использовать LIMIT в некотором роде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...