Lui*_*ese 7 sql sql-server join sql-server-2008
我在输入中有2个字符串,例如'1,5,6'和'2,89,9',具有相同数量的元素(3或加号).我想要的那两个字符串作为"纵坐标连接"
1 2
5 89
6 9
Run Code Online (Sandbox Code Playgroud)
我想要分配一个rownumber并在2个结果集之间建立一个连接
SELECT a.item, b.item FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rownumber,
* FROM dbo.Split('1,5,6',',')
) AS a
INNER JOIN
(
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rownumber,
* FROM dbo.Split('2,89,9',',')
) AS b ON a.rownumber = b.rownumber
Run Code Online (Sandbox Code Playgroud)
这是最好的做法吗?
Mat*_*lie 13
当dbo.Split()
返回数据集时,您所做的任何事情都不能绝对确定地分配您想要的row_number(基于它们在字符串中的顺序).SQL永远不会保证在没有ORDER BY
实际与数据相关的情况下进行排序.
随着你的使用技巧,(SELECT 0)
你可能经常得到正确的价值观.大概十分频繁.但这绝不 保证.偶尔你会得到错误的订单.
您最好的选择是重新编码dbo.Split()
以在解析字符串时分配row_number.只有这样才能100%确定row_number确实对应于项目在列表中的位置.
然后按照您的建议加入它们,并获得您想要的结果.
除此之外,这个想法对我来说似乎没问题.虽然您可能希望考虑FULL OUTER JOIN
一个列表可能比另一个列表更长.
你也可以这样做
考虑你的分裂函数,如下所示:
CREATE FUNCTION Split
(
@delimited nvarchar(max),
@delimiter nvarchar(100)
) RETURNS @t TABLE
(
id int identity(1,1),
val nvarchar(max)
)
AS
BEGIN
declare @xml xml
set @xml = N'<root><r>' + replace(@delimited,@delimiter,'</r><r>') + '</r></root>'
insert into @t(val)
select
r.value('.','varchar(5)') as item
from @xml.nodes('//root/r') as records(r)
RETURN
END
GO
Run Code Online (Sandbox Code Playgroud)
这对JOIN
他们来说将是一项简单的任务.像这样:
SELECT
*
FROM
dbo.Split('1,5,6',',') AS a
JOIN dbo.Split('2,89,9',',') AS b
ON a.id=b.id
Run Code Online (Sandbox Code Playgroud)
这样做的好处是你不需要任何东西 ROW_NUMBER() OVER(ORDER BY SELECT 0)
编辑
与注释一样,使用递归拆分函数可以提高性能.也许是这样的:
CREATE FUNCTION dbo.Split (@s varchar(512),@sep char(1))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
Run Code Online (Sandbox Code Playgroud)
然后选择是这样的:
SELECT
*
FROM
dbo.Split('1,5,6',',') AS a
JOIN dbo.Split('2,89,9',',') AS b
ON a.pn=b.pn
Run Code Online (Sandbox Code Playgroud)