2015-01-01 2 views
1

У меня есть таблица, как показано нижеКак получить все числа от диапазона

Id  RFrom  RTo 
.... ....... ..... 
1  10   14 
1  22   25 
2  100  102 
2  176  180 

Я хочу, чтобы все числа между каждым RFrom и RTO для каждого Id. Мой ожидаемый результат следующий:

Id  NUMS 
.... ...... 
1  10 
1  11 
1  12 
1  13 
1  14 
1  22 
1  23 
1  24 
1  25 
2  100 
2  101 
2  102 
2  176 
2  177 
2  178 
2  179 
2  180 

Должен ли я использовать курсор для достижения этого?

ответ

2

Вот ваш стол

SELECT * INTO #TEMP FROM 
(
    SELECT 1 ID, 10 RFROM, 14 RTO 
    UNION ALL 
    SELECT 1,  22,   25 
    UNION ALL 
    SELECT 2,  100,  102 
    UNION ALL 
    SELECT 2,  176,  180 
)TAB 

образец Вам нужно использовать рекурсию для каждого Id, чтобы получить результат

;WITH CTE AS 
(
    SELECT ID,RFROM RFROM1,RTO RTO1 
    FROM #TEMP 
    UNION ALL 
    SELECT T.ID,RFROM1+1,RTO1 
    FROM #TEMP T 
    JOIN CTE ON CTE.ID = T.ID 
    WHERE RFROM1 < RTO1 
) 
SELECT DISTINCT ID,RFROM1 NUMS 
FROM CTE 
1

Другим вариантом было бы использовать numbers стол с join - рекурсия может занять много времени.

Есть несколько вариантов, чтобы создать таблицу чисел (я бы рекомендовал создать постоянную один), но вот темп один созданный с общим СТОЛОМ-выражением:

with numberstable as (
    select top 10000 row_number() over(order by t1.number) as number 
    from master..spt_values t1 
     cross join master..spt_values t2 
) 
select yt.id, 
    nt.number 
from yourtable yt 
    join numberstable nt on nt.number between yt.rfrom and yt.rto 
+0

Hi sgeddes. Ваш ответ хороший и легкий, но не работает, когда есть отрицательные значения :(В любом случае. Спасибо :) –

+0

@ShilpaPraneesh - не беспокойтесь, рад, что мы помогли. Целью этого решения является не метод, используемый для создания таблицы 'numbers', а скорее преимущества скорости использования' join', чем использование «рекурсивного запроса». Тем не менее, рад, что вы получили его! – sgeddes

+0

Да. Он отлично подходит для + ve значения. Спасибо. Я рад за вашу поддержку :) –

0

Создать tally table с помощью stacked CTE, который будет иметь более высокую производительность по сравнению с recursive CTE

declare @min int 
select @min= min(RFrom) from yourtable 
;WITH e1(n) AS 
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
), -- 10 
e2(n) AS (SELECT 1 FROM e1 CROSS JOIN e1 AS b), -- 10*10 
e3(n) AS (SELECT 1 FROM e1 CROSS JOIN e2) -- 10*100 
SELECT b.id, 
     a.n 
FROM yourtable b 
     JOIN (SELECT n = Row_number()OVER (ORDER BY n)+ @min-1 
      FROM e3)a 
     ON a.n BETWEEN b.RFrom AND b.RTo 
ORDER BY n; 

Проверить here для информации

+0

Это почти то же самое, что и мое опубликованное решение - просто другой подход к созданию таблицы 'numbers'. Основной смысл обоих решений - использовать 'join' с' between' ... – sgeddes

+0

@sgeddes - ваше решение не будет работать, если к основной базе данных невозможно получить доступ к продукту. поэтому избегайте использования основных таблиц базы данных –

+0

Привет NoDisplayName. Не работает, если существуют отрицательные значения :(В любом случае. Спасибо :) –

Смежные вопросы