Я предложил способ выбора @numRows-2
равномерно расположенных строк из @totalCount
строк (более или менее) (псевдокод в {} скобках, то же описание означает тот же код):
declare @numRows int
set @numRows = {how many rows I want}
declare @totalCount bigint
select @totalCount = count(1) from {table}
where {filter condition on indexed rows}
declare @mult float
set @mult = 0.999999999 * (@numRows - 2) / (@totalCount - 1)
select ts.rownum, --debug only
ts.{other data},
...
from
(
select {other data},
...,
ROW_NUMBER() OVER (ORDER BY {ordering}) as rownum
from {table}
where {filter condition on indexed rows}
) as ts
where round(@mult * ts.rownum, 0) <> round((ts.rownum + 1) * @mult, 0)
order by {ordering}
(коэффициент 0,99999 ... заключается в том, чтобы обойти то, что я предполагаю, это ошибки округления чисел с плавающей точкой, приводящие к возвращению дополнительной строки - и это часть того, почему я ищу лучший алгоритм).
Примерырезультатов:
100 из 200: каждый второй ряд
200 из 500: пропустите 2, затем 3, затем 2 и т. д.
100 из 100: все вернулось
100 строк из 50: все возвращено
Я не уверен, что это самый эффективный способ выполнения этого вида фильтрации, но я не могу придумать лучшего способа.Я нашел ответы SQL, которые делают что-то похожее, но не то же самое, и ответы не-SQL, которые делают именно это, но не основаны на множествах.
Предполагая, что в самих данных таблицы нет ничего (например,столбец идентичности), который может помочь с запросом, мне было интересно, если есть вообще более эффективный способ сделать это.Я открыт для временных таблиц результатов.
В случае, если это интересно / актуально: это на встроенном ПК без вентилятора с твердотельным накопителем, 4C Celeron 1,8 ГГц, SQL Server 2014 Express, максимум 500 МБ оперативной памяти, выделенной для SQL.Обычно @numRows=2
, 000 и @totalCount=100
, 000 до 1 000 000.Это для пересчета временных рядов.