在单个字符串中生成以逗号分隔的数字列表
Generate a comma-separated list of numbers in a single string
有没有办法在提供 "begin" 和 "end" 数字的情况下生成以逗号分隔的一系列数字字符串?
例如,提供数字 1 和 10,输出将是单个值:1,2,3,4,5,6,7,8,9,10
10/10/2019 编辑解释我为什么对此感兴趣:
我的工作场所在 SELECT
语句和聚合函数中编写包含多个列的查询。然后是使用列号的 GROUP BY
子句。我认为使用一个为 copy/paste 创建逗号分隔列表的宏会节省一些时间。
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
;
在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
我不确定在 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 因为它很大 table。不过,任何大 table 都可以。
While 循环似乎合适
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
这是在 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
视图中的行数。您始终可以 fiddle 使用它来满足您所需的值范围。
还有 DelimitedBuild
UDF(如果您能找到的话)可用于将行值转换为分隔字符串。
您可以使用递归 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
实现您的目标最便宜的方法是这个(不需要函数,也不需要连接到表):
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
有没有办法在提供 "begin" 和 "end" 数字的情况下生成以逗号分隔的一系列数字字符串?
例如,提供数字 1 和 10,输出将是单个值:1,2,3,4,5,6,7,8,9,10
10/10/2019 编辑解释我为什么对此感兴趣:
我的工作场所在 SELECT
语句和聚合函数中编写包含多个列的查询。然后是使用列号的 GROUP BY
子句。我认为使用一个为 copy/paste 创建逗号分隔列表的宏会节省一些时间。
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
;
在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
我不确定在 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 因为它很大 table。不过,任何大 table 都可以。
While 循环似乎合适
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
这是在 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
视图中的行数。您始终可以 fiddle 使用它来满足您所需的值范围。
还有 DelimitedBuild
UDF(如果您能找到的话)可用于将行值转换为分隔字符串。
您可以使用递归 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
实现您的目标最便宜的方法是这个(不需要函数,也不需要连接到表):
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