英文:
How to separate values into rows
问题
我有这样的数据:
ID | 角色 | 控制单元 | 用户ID |
---|---|---|---|
00196 | SPV / TL / CS | 00G (nol) | 0016506 , 0016551 , 0016541 |
00237 | SPV,CS, TL | 14I | 1458506, 1458541 |
00196 | SPV / CS / TL | 0C3 | 0435506, 0435541, 0435551 |
我想根据它们各自的角色分离用户ID,使其看起来像这样:
ID | 角色 | 控制单元 | 用户ID |
---|---|---|---|
00196 | SPV | 00G (nol) | 0016506 |
00196 | TL | 00G (nol) | 0016551 |
00196 | CS | 00G (nol) | 0016541 |
00237 | SPV | 14I | 1458506 |
00237 | CS | 14I | 1458541 |
00237 | TL | 14I | NULL |
00196 | SPV | 0C3 | 0435506 |
00196 | CS | 0C3 | 0435541 |
00196 | TL | 0C3 | 0435551 |
用户ID的规则如下:
- XXXX506 - XXXX510 = SPV
- XXXX541 - XXXX550 = CS
- XXXX551 - XXXX560 = TL
每个用户ID的前四位数字是分行代码,所以可以忽略它们。只需取每个角色的最后三个数字。
英文:
I have data like this:
ID | Role | Control Unit | User ID |
---|---|---|---|
00196 | SPV / TL / CS | 00G (nol) | 0016506 , 0016551 , 0016541 |
00237 | SPV,CS, TL | 14I | 1458506, 1458541 |
00196 | SPV / CS / TL | 0C3 | 0435506, 0435541, 0435551 |
I want to separate the User ID based on their respective roles, so it looks like this:
ID | Role | Control Unit | User ID |
---|---|---|---|
00196 | SPV | 00G (nol) | 0016506 |
00196 | TL | 00G (nol) | 0016551 |
00196 | CS | 00G (nol) | 0016541 |
00237 | SPV | 14I | 1458506 |
00237 | CS | 14I | 1458541 |
00237 | TL | 14I | NULL |
00196 | SPV | 0C3 | 0435506 |
00196 | CS | 0C3 | 0435541 |
00196 | TL | 0C3 | 0435551 |
The rules of User IDs is:
- XXXX506 - XXXX510 = SPV
- XXXX541 - XXXX550 = CS
- XXXX551 - XXXX560 = TL
The first four digits of each User ID are the branch code, so you can ignore that. Just take the last three numbers for each role.
答案1
得分: 2
请尝试以下的解决方案。
它使用JSON来对标记进行标记。
SQL
-- DDL和示例数据填充,开始
DECLARE @tbl table (ID CHAR(5), ROLE VARCHAR(200), ControlUnit VARCHAR(20), UserID VARCHAR(200))
INSERT @tbl (ID, Role, ControlUnit, UserID) VALUES
('0019', 'SPV / TL / CS', '00G (nol)', '0016506 , 0016551 , 0016541'),
('0023', 'SPV / CS / TL', '14I', '1458506, 1458541, 0435551'),
('0019', 'SPV / CS / TL', '0C3', '0435506, 0435541, 0435551');
-- DDL和示例数据填充,结束
;WITH rs AS
(
SELECT ID, ControlUnit, Role, UserID
, s = '["' + REPLACE(STRING_ESCAPE([Role],'json'), '/', '","') + '"]'
, s1 = '["' + REPLACE(STRING_ESCAPE(UserID,'json'), ',', '","') + '"]'
FROM @tbl
)
SELECT ID, TRIM([Role].[value]) AS [Role], ControlUnit, TRIM(UserID.[value]) AS UserID
FROM rs
CROSS APPLY OPENJSON (s, N'$') AS [Role]
CROSS APPLY OPENJSON (s1, N'$') AS UserID
WHERE [Role].[key] = UserID.[key];
Output
ID | Role | ControlUnit | UserID |
---|---|---|---|
0019 | SPV | 00G (nol) | 0016506 |
0019 | TL | 00G (nol) | 0016551 |
0019 | CS | 00G (nol) | 0016541 |
0023 | SPV | 14I | 1458506 |
0023 | CS | 14I | 1458541 |
0023 | TL | 14I | 0435551 |
0019 | SPV | 0C3 | 0435506 |
0019 | CS | 0C3 | 0435541 |
0019 | TL | 0C3 | 0435551 |
英文:
Please try the following solution.
It is using JSON to tokenize string of tokens.
SQL
-- DDL and sample data population, start
DECLARE @tbl table (ID CHAR(5), ROLE VARCHAR(200), ControlUnit VARCHAR(20), UserID VARCHAR(200))
INSERT @tbl (ID, Role, ControlUnit, UserID) VALUES
('0019', 'SPV / TL / CS', '00G (nol)', '0016506 , 0016551 , 0016541'),
('0023', 'SPV / CS / TL', '14I', '1458506, 1458541, 0435551'),
('0019', 'SPV / CS / TL', '0C3', '0435506, 0435541, 0435551');
-- DDL and sample data population, end
;WITH rs AS
(
SELECT ID, ControlUnit, Role, UserID
, s = '["' + REPLACE(STRING_ESCAPE([Role],'json'), '\/', '","') + '"]'
, s1 = '["' + REPLACE(STRING_ESCAPE(UserID,'json'), ',', '","') + '"]'
FROM @tbl
)
SELECT ID, TRIM([Role].[value]) AS [Role], ControlUnit, TRIM(UserID.[value]) AS UserID
FROM rs
CROSS APPLY OPENJSON (s, N'$') AS [Role]
CROSS APPLY OPENJSON (s1, N'$') AS UserID
WHERE [Role].[key] = UserID.[key];
Output
ID | Role | ControlUnit | UserID |
---|---|---|---|
0019 | SPV | 00G (nol) | 0016506 |
0019 | TL | 00G (nol) | 0016551 |
0019 | CS | 00G (nol) | 0016541 |
0023 | SPV | 14I | 1458506 |
0023 | CS | 14I | 1458541 |
0023 | TL | 14I | 0435551 |
0019 | SPV | 0C3 | 0435506 |
0019 | CS | 0C3 | 0435541 |
0019 | TL | 0C3 | 0435551 |
答案2
得分: 1
你可以使用STRING_SPLIT()函数,只需确保标准化你的分隔符-
- 决定一种分隔符的类型和样式,例如逗号
- 要么确保在数据库中始终只使用此分隔符
- 要么您可以在查询中使用REPLACE()函数来修复它
然后,您可以像这样使用STRING_SPLIT()函数:
SELECT T.ID AS ID,
Roles.RoleName AS Role,
T.[Control Unit] AS [Control Unit],
UserIds.UserId AS [User ID]
FROM UsersToRoles AS T
OUTER APPLY
(
SELECT S.ordinal AS RoleOrder,
S.[value] AS RoleName
FROM STRING_SPLIT(T.[Role], ',') AS S
) AS Roles
OUTER APPLY
(
SELECT S.ordinal AS UserIdOrder,
S.[value] AS UserId
FROM STRING_SPLIT(T.[User ID], ',') AS S
) AS UserIds
WHERE UserIds.UserIdOrder = Roles.RoleOrder
英文:
You can use STRING_SPLIT() function,
just make sure to normalize your separators-
- decide on one type and style of separator, for example comma
- either make sure in DB to always use only this separator
- or you can use REPLACE() functions in your query to fix it
Then you can use the STRING_SPLIT() function like this:
SELECT T.ID AS ID,
Roles.RoleName AS [Role],
T.[Control Unit] AS [Control Unit],
UserIds.UserId AS [User ID]
FROM UsersToRoles AS T
OUTER APPLY
(
SELECT S.ordinal AS RoleOrder,
S.[value] AS RoleName
FROM STRING_SPLIT(T.[Role], ',') AS S
) AS Roles
OUTER APPLY
(
SELECT S.ordinal AS UserIdOrder,
S.[value] AS UserId
FROM STRING_SPLIT(T.[User ID], ',') AS S
) AS UserIds
WHERE UserIds.UserIdOrder = Roles.RoleOrder
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论