在SQL中,我可以将“|”分隔的ID列表转换为它们的值列表吗?
以状态为例,我当前的数据如下在SQL中,我可以将“|”分隔的ID列表转换为它们的值列表吗?,sql,sql-server,tsql,Sql,Sql Server,Tsql,以状态为例,我当前的数据如下 StateAbbrev | NumOfResults ----------- ------------ MD | 5 VA | 2 DC | 7 MD|VA | 2 CA|NY|VA | 1 我希望它输出以下内容 StateName | NumOfResults --------- -------
StateAbbrev | NumOfResults
----------- ------------
MD | 5
VA | 2
DC | 7
MD|VA | 2
CA|NY|VA | 1
我希望它输出以下内容
StateName | NumOfResults
--------- ------------
Maryland | 5
Virginia | 2
District of Columbia | 7
Maryland,Virginia | 2
California,New York,Virginia | 1
我有一个表可以将StateAbbrev映射到StateName
我可以创建一个函数,如果使用管道分隔ID,只需要获取列表,并吐出一个逗号分隔的列表,但是在这种情况下,我有不止一个表,所以我正在寻找一个更干净的解决方案。
谢谢大家! 我使用以下UDF通过 以下是如何使用自定义项的示例:
select [Value] from [dbo].Split('CA|NY|VA', '|')
这将返回一个包含3行的表,每个州一行
更新:
以下是首先进行翻译的完整要求:
declare @cslist varchar(2056)
select @cslist = coalesce(@cslist+',', '') + translated_states.full_state
FROM (
select T2.full_state from [dbo].Split('CA|NY|VA', '|') as T1
JOIN test as T2
on T2.abbr_state = T1.[Value]
) translated_states
select @cslist
如果您对需要更新哪些内容才能使用您的表而不是我的测试表有任何疑问,请告诉我。您可以编写一个C函数,然后使用SQLCLR执行此操作:
或者,您也可以编写一个T-SQL函数来实现这一点 我想出了以下方法,但我必须使用临时表来完成;由于某些原因,子查询无法与子字符串一起使用
DECLARE @T TABLE ( col VARCHAR(1000) )
INSERT INTO @T
( col
)
SELECT 'MD'
UNION ALL
SELECT 'MD|CA'
UNION ALL
SELECT 'MD|CA|VA'
DECLARE @states TABLE
(
abbr VARCHAR(2) ,
StateName VARCHAR(10)
)
INSERT INTO @states
SELECT 'MD' ,
'Maryland'
UNION ALL
SELECT 'CA' ,
'California'
UNION ALL
SELECT 'VA' ,
'Virginia'
SELECT col ,
word = SUBSTRING('|' + col + '|', Number + 1,
CHARINDEX('|', '|' + col + '|', Number + 1) - Number
- 1) ,
Number
INTO #tmp
FROM ( SELECT /*use a table of numbers if you have one instead of this subquery*/
ROW_NUMBER() OVER ( ORDER BY ( ac1.Object_ID ) ) AS Number
FROM Master.sys.columns ac1
) Numbers
CROSS APPLY @t t
WHERE Number >= 1
AND Number < LEN('|' + col + '|') - 1
AND SUBSTRING('|' + col + '|', Number, 1) = '|'
ORDER BY col ,
Number
SELECT t1.col ,
StateName = REPLACE(( SELECT StateName AS [data()]
FROM #tmp t
JOIN @states s ON t.word = s.abbr
WHERE t1.col = t.col
ORDER BY COL ,
Number
FOR
XML PATH('')
), ' ', '|')
FROM #tmp t1
DROP TABLE #tmp
这是一个非UDF解决方案,它使用数字表、XML和交叉应用两次:
DECLARE @Numbers TABLE (Num INT);
INSERT INTO @Numbers VALUES (1);
INSERT INTO @Numbers VALUES (2);
INSERT INTO @Numbers VALUES (3);
INSERT INTO @Numbers VALUES (4);
INSERT INTO @Numbers VALUES (5);
INSERT INTO @Numbers VALUES (6);
INSERT INTO @Numbers VALUES (7);
INSERT INTO @Numbers VALUES (8);
INSERT INTO @Numbers VALUES (9);
DECLARE @Results TABLE (StateAbbrevs VARCHAR(255), NumOfResults INT);
INSERT INTO @Results VALUES ('MD', 5);
INSERT INTO @Results VALUES ('VA', 2);
INSERT INTO @Results VALUES ('DC', 7);
INSERT INTO @Results VALUES ('MD|VA', 2);
INSERT INTO @Results VALUES ('CA|NY|VA', 1);
DECLARE @Abbrev TABLE (StateAbbrev VARCHAR(2), StateName VARCHAR(255));
INSERT INTO @Abbrev VALUES ('MD', 'Maryland');
INSERT INTO @Abbrev VALUES ('VA', 'Virginia');
INSERT INTO @Abbrev VALUES ('DC', 'District of Columbia');
INSERT INTO @Abbrev VALUES ('CA', 'California');
INSERT INTO @Abbrev VALUES ('NY', 'New York');
--SELECT * FROM @Results;
--
--SELECT * FROM @Abbrev;
SELECT STUFF(StateNames, 1, 1, '') AS StateNames,
NumOfResults
FROM @Results AS RESULTS0
CROSS APPLY ( SELECT ',' + ABBREV.StateName
FROM ( SELECT PVT.StateAbbrev,
RESULTS.StateAbbrevs
FROM @Results AS RESULTS
CROSS APPLY ( SELECT SUBSTRING(RESULTS.StateAbbrevs, NUMBERS.Num, CHARINDEX('|', RESULTS.StateAbbrevs + '|', NUMBERS.Num) - NUMBERS.Num) AS StateAbbrev
FROM @Numbers AS NUMBERS
WHERE NUMBERS.Num <= LEN(RESULTS.StateAbbrevs)
AND SUBSTRING('|' + RESULTS.StateAbbrevs, NUMBERS.Num, 1) = '|'
) AS PVT
) AS X
LEFT JOIN @Abbrev AS ABBREV ON ABBREV.StateAbbrev = X.StateAbbrev
WHERE StateAbbrevs = RESULTS0.StateAbbrevs
FOR
XML PATH('')
) AS Y ( StateNames )
这是一个常见的问题,只是用逗号而不是管道。我会在谷歌上搜索堆栈溢出,寻找类似“sql分割逗号”的东西。其实不一样,我熟悉如何分割值,或者生成逗号分隔的列表。在本例中,我希望用实际值替换ID。到目前为止,我想不出一种不需要编写函数的方法。但是我不需要3行,我需要它保持一个逗号分隔的列表,只是有不同的值。所以使用这个函数来分隔,创建另一个函数来获取实际值,并将结果集中到第一个结果字段中。我看不到一种方法可以在本地实现这一点。
DECLARE @Numbers TABLE (Num INT);
INSERT INTO @Numbers VALUES (1);
INSERT INTO @Numbers VALUES (2);
INSERT INTO @Numbers VALUES (3);
INSERT INTO @Numbers VALUES (4);
INSERT INTO @Numbers VALUES (5);
INSERT INTO @Numbers VALUES (6);
INSERT INTO @Numbers VALUES (7);
INSERT INTO @Numbers VALUES (8);
INSERT INTO @Numbers VALUES (9);
DECLARE @Results TABLE (StateAbbrevs VARCHAR(255), NumOfResults INT);
INSERT INTO @Results VALUES ('MD', 5);
INSERT INTO @Results VALUES ('VA', 2);
INSERT INTO @Results VALUES ('DC', 7);
INSERT INTO @Results VALUES ('MD|VA', 2);
INSERT INTO @Results VALUES ('CA|NY|VA', 1);
DECLARE @Abbrev TABLE (StateAbbrev VARCHAR(2), StateName VARCHAR(255));
INSERT INTO @Abbrev VALUES ('MD', 'Maryland');
INSERT INTO @Abbrev VALUES ('VA', 'Virginia');
INSERT INTO @Abbrev VALUES ('DC', 'District of Columbia');
INSERT INTO @Abbrev VALUES ('CA', 'California');
INSERT INTO @Abbrev VALUES ('NY', 'New York');
--SELECT * FROM @Results;
--
--SELECT * FROM @Abbrev;
SELECT STUFF(StateNames, 1, 1, '') AS StateNames,
NumOfResults
FROM @Results AS RESULTS0
CROSS APPLY ( SELECT ',' + ABBREV.StateName
FROM ( SELECT PVT.StateAbbrev,
RESULTS.StateAbbrevs
FROM @Results AS RESULTS
CROSS APPLY ( SELECT SUBSTRING(RESULTS.StateAbbrevs, NUMBERS.Num, CHARINDEX('|', RESULTS.StateAbbrevs + '|', NUMBERS.Num) - NUMBERS.Num) AS StateAbbrev
FROM @Numbers AS NUMBERS
WHERE NUMBERS.Num <= LEN(RESULTS.StateAbbrevs)
AND SUBSTRING('|' + RESULTS.StateAbbrevs, NUMBERS.Num, 1) = '|'
) AS PVT
) AS X
LEFT JOIN @Abbrev AS ABBREV ON ABBREV.StateAbbrev = X.StateAbbrev
WHERE StateAbbrevs = RESULTS0.StateAbbrevs
FOR
XML PATH('')
) AS Y ( StateNames )