SQL-запрос для извлечения чисел в заданных шагах между диапазонами - PullRequest
2 голосов
/ 21 декабря 2011

У меня есть такой набор данных:

MinNo: 2500
MaxNo: 2700
IncrementStep: 10

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

2500
2510
2520
2530
2540
2550
2560
2570
2580
2590
2600
2610
2620
2630
2640
2650
2660
2670
2680
2690
2700

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

Ответы [ 3 ]

4 голосов
/ 21 декабря 2011

Вы можете использовать таблицу чисел (или master..spt_values).

declare @MinNo int
declare @MaxNo int
declare @IncrementStep int

set @MinNo = 2500
set @MaxNo = 2700
set @IncrementStep = 10

select @MinNo + Number * @IncrementStep
from master..spt_values
where type = 'P' and
      number between 0 and (@MaxNo - @MinNo) / @IncrementStep

Или рекурсивный CTE

;with C as
(
  select @MinNo as Num
  union all 
  select Num + @IncrementStep
  from C
  where Num < @MaxNo
)      
select Num
from C
1 голос
/ 21 декабря 2011

@ Микаэль Эрикссон уже упоминал таблицу номеров / счетную таблицу (ищите ее в Интернете, существует множество возможных вариантов использования, многие администраторы баз данных всегда хотят, чтобы таблица учета была представлена ​​в любой системе, которой они управляют)

IЯ просто хотел поделиться одним нерекурсивным решением «Tally Table» на основе CTE, которое я видел на днях, и которое, я думаю, удивительно элегантно благодаря своему огромному диапазону (4 тысячи миллионов логических строк) и общей применимости без каких-либо зависимостей от базы данных:

WITH 
        E00(N) AS (SELECT 1 UNION ALL SELECT 1),
        E02(N) AS (SELECT 1 FROM E00 a, E00 b),
        E04(N) AS (SELECT 1 FROM E02 a, E02 b),
        E08(N) AS (SELECT 1 FROM E04 a, E04 b),
        E16(N) AS (SELECT 1 FROM E08 a, E08 b),
        E32(N) AS (SELECT 1 FROM E16 a, E16 b),
   cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT *
FROM cteTally
WHERE N >= 2500 
    AND N <= 2700
    AND N % 10 = 0

Я нашел это здесь , но я не знаю, является ли это исходным источником этого CTE.

Приятно, что вы этого не делаетеНе нужно беспокоиться о минимальном, максимальном или размере шага, и все же он работает очень хорошо в большинстве (разовых) ситуаций.Тем не менее, он не должен использоваться в каких-либо часто называемых бизнес-процессах;Любая таблица с физическими индексированными числами всегда будет работать лучше!

РЕДАКТИРОВАТЬ: я просто немного больше искал источник этого метода (я пропустил ссылку на stackoverflow в статье, на которую я ссылался), и, по-видимому, первоначально она была приписанаИцик Бен-Ган, из нижней части страницы 255 в книге под названием «Внутри Microsoft SQL Server 2005 - T-SQL Querying» ( говорит Джефф Моден , которому я безоговорочно доверяю).

1 голос
/ 21 декабря 2011

Смотрите эту полезную функцию

CREATE FUNCTION [dbo].[Sequence](@min INT, @max INT, @step INT)
RETURNS @ret TABLE (id INT PRIMARY KEY)
AS
BEGIN
    WITH numbers(id) as
    (
        SELECT @min id
        UNION ALL 
        SELECT id+@step
        FROM numbers
        WHERE id < @max
    )
    INSERT @ret 
    SELECT id FROM Numbers
    OPTION(MAXRECURSION 0)
    RETURN
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...