将有序 String_Split 的结果连接到一个变量中
Concatenate the result of an ordered String_Split in a variable
在我使用的 Sql 服务器数据库中,数据库名称类似于 StackExchange.Audio.Meta
、StackExchange.Audio
或 Whosebug
。幸运的是,这也是一个网站的 url。我只需要在点上拆分它并反转它:meta.audio.stackexchange
。添加 http://
和 .com
就完成了。显然Whosebug
不需要任何反转。
使用 SqlServer 2016 string_split 函数,我可以轻松拆分和重新排序其结果:
select value
from string_split(db_name(),'.')
order by row_number() over( order by (select 1)) desc
这给了我
| Value |
-----------------
| Meta |
| Audio |
| StackExchange |
因为我需要在变量中包含 url 我希望使用这个 answer 连接它所以我的尝试看起来像这样:
declare @revname nvarchar(150)
select @revname = coalesce(@revname +'.','') + value
from string_split(db_name(),'.')
order by row_number() over( order by (select 1)) desc
然而这只是 returns 我的最后一个值,StackExchange
。我已经注意到该答案中的警告,该技巧仅适用于某些执行计划,如 here.
所述
问题似乎是由 order by
子句引起的。如果没有它,我将获得所有值,但顺序错误。我尝试按照 Microsoft 文章中的建议添加 ltrim
和 rtrim
函数以及子查询,但到目前为止没有运气。
有没有办法让 Sql Server 2016 查询引擎将 string_split
的有序结果连接到变量中?
我知道我可以使用 for XML
甚至普通光标来获得我需要的结果,但我还不想放弃这个优雅的解决方案。
因为我是 运行 在 Stack Exchange Data Explorer 上,所以我无法使用函数,因为我们没有创建这些函数的权限。我可以执行存储过程,但我希望我可以避开这些。
我准备了一个SEDE Query to experiment with. The database names to expect are either without dots, aka Whosebug
, with 1 dot: Whosebug.Meta
or 2 dots, `StackExchange.Audio.Meta, the full list of databases is here
我认为你把事情复杂化了。你可以使用 PARSENAME
:
SELECT 'http://' + PARSENAME(db_name(),1) +
ISNULL('.' + PARSENAME(db_name(),2),'') + ISNULL('.'+PARSENAME(db_name(),3),'')
+ '.com'
这正是我在拆分函数中使用演示序列 (PS) 的原因。人们经常嘲笑对此类项目使用 UDF,但解析某些内容供以后使用通常是一次性的。
Select * from [dbo].[udf-Str-Parse]('meta.audio.stackexchange','.')
Returns
Key_PS Key_Value
1 meta
2 audio
3 stackexchange
UDF
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@delimeter varchar(10))
--Usage: Select * from [dbo].[udf-Str-Parse]('meta.audio.stackexchange','.')
-- Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
-- Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|')
Returns @ReturnTable Table (Key_PS int IDENTITY(1,1) NOT NULL , Key_Value varchar(max))
As
Begin
Declare @intPos int,@SubStr varchar(max)
Set @IntPos = CharIndex(@delimeter, @String)
Set @String = Replace(@String,@delimeter+@delimeter,@delimeter)
While @IntPos > 0
Begin
Set @SubStr = Substring(@String, 0, @IntPos)
Insert into @ReturnTable (Key_Value) values (@SubStr)
Set @String = Replace(@String, @SubStr + @delimeter, '')
Set @IntPos = CharIndex(@delimeter, @String)
End
Insert into @ReturnTable (Key_Value) values (@String)
Return
End
可能不太优雅的解决方案,但它只需要几行并且可以使用任意数量的点。
;with cte as (--build xml
select 1 num, cast('<str><s>'+replace(db_name(),'.','</s><s>')+'</s></str>' as xml) str
)
,x as (--make table from xml
select row_number() over(order by num) rn, --add numbers to sort later
t.v.value('.[1]','varchar(50)') s
from cte cross apply cte.str.nodes('str/s') t(v)
)
--combine into string
select STUFF((SELECT '.' + s AS [text()]
FROM x
order by rn desc --in reverse order
FOR XML PATH('')
), 1, 1, '' ) name
Is there a way I can nudge the Sql Server 2016 Query Engine to concatenate the ordered result from that string_split in a variable?
你可以只使用 CONCAT
:
DECLARE @URL NVARCHAR(MAX)
SELECT @URL = CONCAT(value, '.', @URL) FROM STRING_SPLIT(DB_NAME(), '.')
SET @URL = CONCAT('http://', LOWER(@URL), 'com');
反转是通过参数的顺序完成的CONCAT
。 Here's an example.
它将 StackExchange.Garage.Meta
更改为 http://meta.garage.stackexchange.com
。
这通常可用于拆分和反转字符串,但请注意它确实会留下尾随分隔符。我确定您可以在其中添加一些逻辑或 COALESCE
来避免这种情况发生。
另请注意,vNext 将添加 STRING_AGG
。
为了回答这个 XY 问题的 'X',并解决 HTTPS 切换(特别是对于 Meta 站点)和一些其他站点名称更改,我写了以下内容 SEDE query which outputs all site names in the format used on the network site list。
SELECT name,
LOWER('https://' +
IIF(PATINDEX('%.Mathoverflow%', name) > 0,
IIF(PATINDEX('%.Meta', name) > 0, 'meta.mathoverflow.net', 'mathoverflow.net'),
IIF(PATINDEX('%.Ubuntu%', name) > 0,
IIF(PATINDEX('%.Meta', name) > 0, 'meta.askubuntu.com', 'askubuntu.com'),
IIF(PATINDEX('StackExchange.%', name) > 0,
CASE SUBSTRING(name, 15, 200)
WHEN 'Audio' THEN 'video'
WHEN 'Audio.Meta' THEN 'video.meta'
WHEN 'Beer' THEN 'alcohol'
WHEN 'Beer.Meta' THEN 'alcohol.meta'
WHEN 'CogSci' THEN 'psychology'
WHEN 'CogSci.Meta' THEN 'psychology.meta'
WHEN 'Garage' THEN 'mechanics'
WHEN 'Garage.Meta' THEN 'mechanics.meta'
WHEN 'Health' THEN 'medicalsciences'
WHEN 'Health.Meta' THEN 'medicalsciences.meta'
WHEN 'Moderators' THEN 'communitybuilding'
WHEN 'Moderators.Meta' THEN 'communitybuilding.meta'
WHEN 'Photography' THEN 'photo'
WHEN 'Photography.Meta' THEN 'photo.meta'
WHEN 'Programmers' THEN 'softwareengineering'
WHEN 'Programmers.Meta' THEN 'softwareengineering.meta'
WHEN 'Vegetarian' THEN 'vegetarianism'
WHEN 'Vegetarian.Meta' THEN 'vegetarianism.meta'
WHEN 'Writers' THEN 'writing'
WHEN 'Writers.Meta' THEN 'writing.meta'
ELSE SUBSTRING(name, 15, 200)
END + '.stackexchange.com',
IIF(PATINDEX('Whosebug.%', name) > 0,
CASE SUBSTRING(name, 15, 200)
WHEN 'Br' THEN 'pt'
WHEN 'Br.Meta' THEN 'pt.meta'
ELSE SUBSTRING(name, 15, 200)
END + '.whosebug.com',
IIF(PATINDEX('%.Meta', name) > 0,
'meta.' + SUBSTRING(name, 0, PATINDEX('%.Meta', name)) + '.com',
name + '.com'
)
)
)
)
) + '/'
)
FROM sys.databases WHERE database_id > 5
在我使用的 Sql 服务器数据库中,数据库名称类似于 StackExchange.Audio.Meta
、StackExchange.Audio
或 Whosebug
。幸运的是,这也是一个网站的 url。我只需要在点上拆分它并反转它:meta.audio.stackexchange
。添加 http://
和 .com
就完成了。显然Whosebug
不需要任何反转。
使用 SqlServer 2016 string_split 函数,我可以轻松拆分和重新排序其结果:
select value
from string_split(db_name(),'.')
order by row_number() over( order by (select 1)) desc
这给了我
| Value |
-----------------
| Meta |
| Audio |
| StackExchange |
因为我需要在变量中包含 url 我希望使用这个 answer 连接它所以我的尝试看起来像这样:
declare @revname nvarchar(150)
select @revname = coalesce(@revname +'.','') + value
from string_split(db_name(),'.')
order by row_number() over( order by (select 1)) desc
然而这只是 returns 我的最后一个值,StackExchange
。我已经注意到该答案中的警告,该技巧仅适用于某些执行计划,如 here.
问题似乎是由 order by
子句引起的。如果没有它,我将获得所有值,但顺序错误。我尝试按照 Microsoft 文章中的建议添加 ltrim
和 rtrim
函数以及子查询,但到目前为止没有运气。
有没有办法让 Sql Server 2016 查询引擎将 string_split
的有序结果连接到变量中?
我知道我可以使用 for XML
甚至普通光标来获得我需要的结果,但我还不想放弃这个优雅的解决方案。
因为我是 运行 在 Stack Exchange Data Explorer 上,所以我无法使用函数,因为我们没有创建这些函数的权限。我可以执行存储过程,但我希望我可以避开这些。
我准备了一个SEDE Query to experiment with. The database names to expect are either without dots, aka Whosebug
, with 1 dot: Whosebug.Meta
or 2 dots, `StackExchange.Audio.Meta, the full list of databases is here
我认为你把事情复杂化了。你可以使用 PARSENAME
:
SELECT 'http://' + PARSENAME(db_name(),1) +
ISNULL('.' + PARSENAME(db_name(),2),'') + ISNULL('.'+PARSENAME(db_name(),3),'')
+ '.com'
这正是我在拆分函数中使用演示序列 (PS) 的原因。人们经常嘲笑对此类项目使用 UDF,但解析某些内容供以后使用通常是一次性的。
Select * from [dbo].[udf-Str-Parse]('meta.audio.stackexchange','.')
Returns
Key_PS Key_Value
1 meta
2 audio
3 stackexchange
UDF
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@delimeter varchar(10))
--Usage: Select * from [dbo].[udf-Str-Parse]('meta.audio.stackexchange','.')
-- Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
-- Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|')
Returns @ReturnTable Table (Key_PS int IDENTITY(1,1) NOT NULL , Key_Value varchar(max))
As
Begin
Declare @intPos int,@SubStr varchar(max)
Set @IntPos = CharIndex(@delimeter, @String)
Set @String = Replace(@String,@delimeter+@delimeter,@delimeter)
While @IntPos > 0
Begin
Set @SubStr = Substring(@String, 0, @IntPos)
Insert into @ReturnTable (Key_Value) values (@SubStr)
Set @String = Replace(@String, @SubStr + @delimeter, '')
Set @IntPos = CharIndex(@delimeter, @String)
End
Insert into @ReturnTable (Key_Value) values (@String)
Return
End
可能不太优雅的解决方案,但它只需要几行并且可以使用任意数量的点。
;with cte as (--build xml
select 1 num, cast('<str><s>'+replace(db_name(),'.','</s><s>')+'</s></str>' as xml) str
)
,x as (--make table from xml
select row_number() over(order by num) rn, --add numbers to sort later
t.v.value('.[1]','varchar(50)') s
from cte cross apply cte.str.nodes('str/s') t(v)
)
--combine into string
select STUFF((SELECT '.' + s AS [text()]
FROM x
order by rn desc --in reverse order
FOR XML PATH('')
), 1, 1, '' ) name
Is there a way I can nudge the Sql Server 2016 Query Engine to concatenate the ordered result from that string_split in a variable?
你可以只使用 CONCAT
:
DECLARE @URL NVARCHAR(MAX)
SELECT @URL = CONCAT(value, '.', @URL) FROM STRING_SPLIT(DB_NAME(), '.')
SET @URL = CONCAT('http://', LOWER(@URL), 'com');
反转是通过参数的顺序完成的CONCAT
。 Here's an example.
它将 StackExchange.Garage.Meta
更改为 http://meta.garage.stackexchange.com
。
这通常可用于拆分和反转字符串,但请注意它确实会留下尾随分隔符。我确定您可以在其中添加一些逻辑或 COALESCE
来避免这种情况发生。
另请注意,vNext 将添加 STRING_AGG
。
为了回答这个 XY 问题的 'X',并解决 HTTPS 切换(特别是对于 Meta 站点)和一些其他站点名称更改,我写了以下内容 SEDE query which outputs all site names in the format used on the network site list。
SELECT name,
LOWER('https://' +
IIF(PATINDEX('%.Mathoverflow%', name) > 0,
IIF(PATINDEX('%.Meta', name) > 0, 'meta.mathoverflow.net', 'mathoverflow.net'),
IIF(PATINDEX('%.Ubuntu%', name) > 0,
IIF(PATINDEX('%.Meta', name) > 0, 'meta.askubuntu.com', 'askubuntu.com'),
IIF(PATINDEX('StackExchange.%', name) > 0,
CASE SUBSTRING(name, 15, 200)
WHEN 'Audio' THEN 'video'
WHEN 'Audio.Meta' THEN 'video.meta'
WHEN 'Beer' THEN 'alcohol'
WHEN 'Beer.Meta' THEN 'alcohol.meta'
WHEN 'CogSci' THEN 'psychology'
WHEN 'CogSci.Meta' THEN 'psychology.meta'
WHEN 'Garage' THEN 'mechanics'
WHEN 'Garage.Meta' THEN 'mechanics.meta'
WHEN 'Health' THEN 'medicalsciences'
WHEN 'Health.Meta' THEN 'medicalsciences.meta'
WHEN 'Moderators' THEN 'communitybuilding'
WHEN 'Moderators.Meta' THEN 'communitybuilding.meta'
WHEN 'Photography' THEN 'photo'
WHEN 'Photography.Meta' THEN 'photo.meta'
WHEN 'Programmers' THEN 'softwareengineering'
WHEN 'Programmers.Meta' THEN 'softwareengineering.meta'
WHEN 'Vegetarian' THEN 'vegetarianism'
WHEN 'Vegetarian.Meta' THEN 'vegetarianism.meta'
WHEN 'Writers' THEN 'writing'
WHEN 'Writers.Meta' THEN 'writing.meta'
ELSE SUBSTRING(name, 15, 200)
END + '.stackexchange.com',
IIF(PATINDEX('Whosebug.%', name) > 0,
CASE SUBSTRING(name, 15, 200)
WHEN 'Br' THEN 'pt'
WHEN 'Br.Meta' THEN 'pt.meta'
ELSE SUBSTRING(name, 15, 200)
END + '.whosebug.com',
IIF(PATINDEX('%.Meta', name) > 0,
'meta.' + SUBSTRING(name, 0, PATINDEX('%.Meta', name)) + '.com',
name + '.com'
)
)
)
)
) + '/'
)
FROM sys.databases WHERE database_id > 5