如何在 SQL 的单列中使用多个 ID 从 table 获取值?
How to get values from table using multiple ID's in single column in SQL?
我正在使用现有的存储过程。在那里,他们使用 select 查询获取一些数据。现在我正在尝试获取更多数据。我遇到的问题是,我用来从另一个 table 获取数据的列中保存了多个 Id,中间用逗号 (,) 保存。
2 tables 的程序为 Tbl_av,Tbl_aa.
我在 Tbl_av 中有一列作为 processId 在 Varchar[=60= 中] 并存储 1,2,4 等数据。(即,它存储进程的 ID)。
现在我正在尝试使用 table [=45] 下的此 ProcessId 从另一个 table Tbl_Process 获取进程名称=]Tbl_av。在 table、 中,进程 ID 是唯一的,并且是整数。
Tbl_Process如下:
Tbl_av如下:
我有以下几部分程序:
SET @strQuery= 'SELECT isnull(av.ID, 0) AS ID
,isnull(ItemNumber, '''') AS Number
,isnull(av.ItemName,'''') as Item Name
,av.Description
,(select top 1 Name from TBL_Names where Id =aa.id)as Person Incharge from Tbl_AV av, Tbl_aa aa WHERE av.S_number = aa.S_number'
现在我要做的是,我需要使用 Tbl_av[从 Tbl_Process 中获取进程名称 ProcessId's inside the procedure.
我不知道如何实现它,因为它的两列都是不同的数据类型,并且在一列中保存了超过 1 个 ID
注意:我们可以简单地实现这一点 'SELECT Process_Name from Tbl_Process WHERE Id in (av.ProcessId)'
- 但是这样做会以列格式显示数据。
我希望数据被 select 编辑,就好像 Id 是 1,2 意味着我希望我的输出为 Process_Name = Item 1,Item 2.
请帮忙。
需要两个技巧。一种是根据 comma-separated ID 列表加入。这很容易做得不好,导致不需要的匹配,例如 1 和 2 匹配 12。Stephen Jennings 引用的文章有一些很好的可靠解决方案。
第二个是将一组结果连接成一个字符串。对于最新版本的 SQL 服务器,STRING_AGG 是首选解决方案。对于旧版本(例如 2014),最常用的方法是“FOR XML”技巧。
我结合了以下两种技术。
DECLARE @Tbl_Process TABLE(ID INT, process_Name VARCHAR(100))
INSERT @Tbl_Process
VALUES (1, 'Item 1'), (2, 'Item 2'), (3, 'Item 3'), (4, 'Item 4'), (5, 'Item 5'), (12, 'Item 12')
DECLARE @Tbl_av TABLE(ID INT, ProcessId VARCHAR(100))
INSERT @Tbl_av
VALUES (1, '1,3,5'), (2, '2,4'), (3, '1,2,3'), (4, '1,5'), (5, ''), (6, '3,4,12')
SELECT AV.*, PL.*
FROM @Tbl_av AV
CROSS APPLY (
SELECT ISNULL(STUFF(
(
SELECT ',' + P.process_Name
FROM @Tbl_Process P
--(bad) WHERE CHARINDEX(CONVERT(VARCHAR, P.ID), AV.ProcessId) > 0
WHERE ',' + AV.ProcessId + ',' LIKE '%,' + CONVERT(VARCHAR, P.ID) + ',%'
ORDER BY P.ID -- alternately ORDER BY P.process_Name
FOR XML PATH(''), TYPE
).value('text()[1]','nvarchar(max)')
, 1, 1, '')
, '(none)')
AS Process_Names
) PL
结果
ID
ProcessId
Process_Names
1
1,3,5
Item 1,Item 3,Item 5
2
2,4
Item 2,Item 4
3
1,2,3
Item 1,Item 2,Item 3
4
1,5
Item 1,Item 5
5
(none)
6
3,4,12
Item 3,Item 4,Item 12
FOR XML PATH('')
技巧导致结果连接成单个 XML 字符串,没有标签。 , TYPE
与 .value('text()[1]','nvarchar(max)')
一起安全地提取结果文本,撤销任何 XML 特定文本编码,例如 &
、<
或 >
。 STUFF() 删除前导逗号,如果没有值,ISNULL() 提供默认值。
有关 FOR XML 技巧如何工作的更多信息,请参阅 How Stuff and 'For Xml Path' work in SQL Server?。
如果您更喜欢 comma-space 列表分隔符,您可以更新 ','
,但还需要调整 STUFF 以去除两个字符而不是一个。
交叉应用的内容可以直接移动到 SELECT 子句中,但作为样式问题,CROSS APPLY 允许将复杂逻辑与查询的其余部分分开。
我正在使用现有的存储过程。在那里,他们使用 select 查询获取一些数据。现在我正在尝试获取更多数据。我遇到的问题是,我用来从另一个 table 获取数据的列中保存了多个 Id,中间用逗号 (,) 保存。
2 tables 的程序为 Tbl_av,Tbl_aa.
我在 Tbl_av 中有一列作为 processId 在 Varchar[=60= 中] 并存储 1,2,4 等数据。(即,它存储进程的 ID)。
现在我正在尝试使用 table [=45] 下的此 ProcessId 从另一个 table Tbl_Process 获取进程名称=]Tbl_av。在 table、 中,进程 ID 是唯一的,并且是整数。
Tbl_Process如下:
Tbl_av如下:
我有以下几部分程序:
SET @strQuery= 'SELECT isnull(av.ID, 0) AS ID
,isnull(ItemNumber, '''') AS Number
,isnull(av.ItemName,'''') as Item Name
,av.Description
,(select top 1 Name from TBL_Names where Id =aa.id)as Person Incharge from Tbl_AV av, Tbl_aa aa WHERE av.S_number = aa.S_number'
现在我要做的是,我需要使用 Tbl_av[从 Tbl_Process 中获取进程名称 ProcessId's inside the procedure.
我不知道如何实现它,因为它的两列都是不同的数据类型,并且在一列中保存了超过 1 个 ID
注意:我们可以简单地实现这一点 'SELECT Process_Name from Tbl_Process WHERE Id in (av.ProcessId)'
- 但是这样做会以列格式显示数据。
我希望数据被 select 编辑,就好像 Id 是 1,2 意味着我希望我的输出为 Process_Name = Item 1,Item 2.
请帮忙。
需要两个技巧。一种是根据 comma-separated ID 列表加入。这很容易做得不好,导致不需要的匹配,例如 1 和 2 匹配 12。Stephen Jennings 引用的文章有一些很好的可靠解决方案。
第二个是将一组结果连接成一个字符串。对于最新版本的 SQL 服务器,STRING_AGG 是首选解决方案。对于旧版本(例如 2014),最常用的方法是“FOR XML”技巧。
我结合了以下两种技术。
DECLARE @Tbl_Process TABLE(ID INT, process_Name VARCHAR(100))
INSERT @Tbl_Process
VALUES (1, 'Item 1'), (2, 'Item 2'), (3, 'Item 3'), (4, 'Item 4'), (5, 'Item 5'), (12, 'Item 12')
DECLARE @Tbl_av TABLE(ID INT, ProcessId VARCHAR(100))
INSERT @Tbl_av
VALUES (1, '1,3,5'), (2, '2,4'), (3, '1,2,3'), (4, '1,5'), (5, ''), (6, '3,4,12')
SELECT AV.*, PL.*
FROM @Tbl_av AV
CROSS APPLY (
SELECT ISNULL(STUFF(
(
SELECT ',' + P.process_Name
FROM @Tbl_Process P
--(bad) WHERE CHARINDEX(CONVERT(VARCHAR, P.ID), AV.ProcessId) > 0
WHERE ',' + AV.ProcessId + ',' LIKE '%,' + CONVERT(VARCHAR, P.ID) + ',%'
ORDER BY P.ID -- alternately ORDER BY P.process_Name
FOR XML PATH(''), TYPE
).value('text()[1]','nvarchar(max)')
, 1, 1, '')
, '(none)')
AS Process_Names
) PL
结果
ID | ProcessId | Process_Names |
---|---|---|
1 | 1,3,5 | Item 1,Item 3,Item 5 |
2 | 2,4 | Item 2,Item 4 |
3 | 1,2,3 | Item 1,Item 2,Item 3 |
4 | 1,5 | Item 1,Item 5 |
5 | (none) | |
6 | 3,4,12 | Item 3,Item 4,Item 12 |
FOR XML PATH('')
技巧导致结果连接成单个 XML 字符串,没有标签。 , TYPE
与 .value('text()[1]','nvarchar(max)')
一起安全地提取结果文本,撤销任何 XML 特定文本编码,例如 &
、<
或 >
。 STUFF() 删除前导逗号,如果没有值,ISNULL() 提供默认值。
有关 FOR XML 技巧如何工作的更多信息,请参阅 How Stuff and 'For Xml Path' work in SQL Server?。
如果您更喜欢 comma-space 列表分隔符,您可以更新 ','
,但还需要调整 STUFF 以去除两个字符而不是一个。
交叉应用的内容可以直接移动到 SELECT 子句中,但作为样式问题,CROSS APPLY 允许将复杂逻辑与查询的其余部分分开。