Эффективный выбор каждой n-й строки из таблицы SQL, где n не является целым числом - PullRequest
0 голосов
/ 02 июня 2018

Я предложил способ выбора @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.Это для пересчета временных рядов.

...