Создать разделенный запятыми список чисел в одной строке - PullRequest
0 голосов
/ 04 октября 2019

Есть ли способ сгенерировать разделенную запятыми строку из серии чисел, в которой указаны числа "начало" и "конец"?

Например, укажите числа 1 и 10 и выводбудет одно значение: 1,2,3,4,5,6,7,8,9,10

10/10 / 2019 edit, объясняющее, почему я заинтересован в этом:

Мое рабочее место записывает запросы с несколькими столбцами в выражении SELECTплюс агрегатные функции. Затем предложение GROUP BY с использованием номеров столбцов. Я полагал, что использование макроса, который создает разделенный запятыми список для копирования / вставки, сэкономит время.

SELECT t.colA
     , t.colB
     , t.colC
     , t.colD
     , t.colE
     , t.colF
     , t.colG
     , t.colH
     , t.colI
     , t.colJ
     , sum(t.colK) as sumK
     , sum(t.colL) as sumL
     , sum(t.colM) as sumM
  FROM t
 GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
;

Ответы [ 6 ]

0 голосов
/ 12 октября 2019

Самый дешевый способ достижения вашей цели - это один (без функций или соединений с таблицами):

WITH RECURSIVE NumberRanges(TheNumber,TheString) AS
(
SELECT 1 AS TheNumber,casT(1 as VARCHAR(500)) as TheString

FROM
( 
  SELECT * FROM (SELECT NULL AS X) X
) DUMMYTABLE
UNION ALL
SELECT
    TheNumber + 1 AS TheNumber,
    TheString ||',' || TRIM(TheNumber+1) 

FROM NumberRanges
WHERE
TheNumber < 10
)
SELECT TheString
FROM NumberRanges
QUALIFY ROW_NUMBER() OVER ( ORDER BY TheNumber DESC) = 1;

Строка результата: 1,2,3,4,5,6,7,8,9,10

0 голосов
/ 04 октября 2019

Вы можете использовать рекурсивный CTE для генерации ваших чисел и xml_agg для генерации вашей строки:

with  recursive nums (counter) as
( select * from (select  cast(1 as bigint) as counter) t
union all
select
counter + 1
from nums
where counter between 1 and 9
)
 select 
 trim(trailing ',' from cast(xmlagg(cast(counter as varchar(2)) || ',' order by counter) as varchar(100)))
 from nums
0 голосов
/ 04 октября 2019

Вот один из способов сделать это в Teradata:

SELECT ARRAY_AGG(src.RowNum) 
FROM (
  SELECT ROW_NUMBER() OVER() AS RowNum
  FROM sys_calendar.calendar
  QUALIFY RowNum BETWEEN <begin_num> AND <end_num>
) src

Это даст вам вывод в виде ARRAY типа данных, который вы, вероятно, можете преобразовать в VARCHAR. Также предполагается, что begin_num > 0 и <end_num> меньше количества строк в представлении sys_calendar.calendar. Вы всегда можете поиграть с этим, чтобы соответствовать требуемому диапазону значений.

Существуют также DelimitedBuild UDF (если вы можете их найти), которые можно использовать для преобразования значений строк в строки с разделителями.

0 голосов
/ 04 октября 2019

Хотя цикл кажется подходящим

declare @begin int=1
declare @end int=11

declare @list varchar(500)

if @begin > @end
    begin
        select 'error, beginning number ' + convert(varchar(500),@begin)
        + ' must not be greater than ending number '
        + convert(varchar(500),@end) + '.' err
        return
    end
    else
        set @list = convert(varchar(500),@begin)
;
while @begin < @end
    begin
        set @begin += 1
        set @list = @list + ',' + convert(varchar(500),@begin)
    end

select @list

Вы можете использовать varchar (5000) или что-то еще, в зависимости от того, насколько большим вы хотите его получить.

disclaimer -- I don't know if this works with teradata

0 голосов
/ 04 октября 2019

Я не уверен, что есть хороший прямой способ создать серию в Teradata. Вы можете подделать его несколькими разными способами. Вот разделенный запятыми список чисел от 5 до 15, например:

SELECT TRIM(TRAILING ',' FROM (XMLAGG(TRIM(rn)|| ',' ) (VARCHAR(10000))))
FROM (SELECT 4 + ROW_NUMBER() OVER (ORDER BY Sys_Calendar."CALENDAR".day_of_calendar) as rn FROM Sys_Calendar."CALENDAR" QUALIFY rn <= 15) t

Я использовал здесь только sys_calendar.calendar, потому что это большая таблица. Любой большой стол подойдет здесь.

0 голосов
/ 04 октября 2019

Проверьте эти методы в SQL Server-

IF OBJECT_ID('TEMPDB..#Sample') IS NOT NULL 
    DROP TABLE #Sample

Create table #Sample 
(
NUM int
)

declare @n int
select @n=10
insert into #Sample(NUM) 
SELECT NUM FROM (select row_number() over (order by (select null)) AS NUM from sys.columns) A WHERE NUM<=@N

--Method 1 (For SQL SERVER -NEW VERSION Support)
SELECT STRING_AGG(NUM,',') AS EXPECTED_RESULT FROM #Sample
--Method 1 (For SQL SERVER -OLD VERSION Support)
select DISTINCT STUFF(CAST((
    SELECT   ' ,' +CAST(c.num AS VARCHAR(MAX))
    FROM (  
            SELECT num
            FROM   #Sample
        ) c
    FOR XML PATH(''), TYPE) AS VARCHAR(MAX)), 1, 2, '') AS EXPECTED_RESULT
    from #Sample t
...