[英]Split column, and then convert different date types to standard date format (YYYY-MM-DD) - SQL Server
我需要将列拆分为 2 个单独的列,然后将多个日期类型列转换为标准日期格式列。
CREATE TABLE Report
(Id INT, Reference VARCHAR(30));
INSERT INTO Report
VALUES
(1, 'Location (11/8/22)'),
(2, 'Timesheet (11/10/22)'),
(3, 'TESTING (12/09/22)'),
(4, 'Incorrect Payment (9/10/22)'),
(5, 'Employee (11/9/22)'),
(6, 'Authorization'),
(7, 'Inactive Client'),
(8, 'Active Client (07/22/2022)'),
(9, 'TESTING (09/09/22)'),
(10, 'Timesheet')
SELECT * FROM Report
ID | 参考 |
---|---|
1个 | 位置 (11/8/22) |
2个 | 时间表 (11/10/22) |
3个 | 测试 (12/09/22) |
4个 | 付款不正确 (9/10/22) |
5个 | 员工 (11/9/22) |
6个 | 授权 |
7 | 不活跃的客户 |
8个 | 活跃客户 (07/22/2022) |
9 | 测试 (09/09/22) |
10 | 时间表 |
我需要的输出:
ID | 参考 | 类型 | 日期 |
---|---|---|---|
1个 | 位置 (11/8/22) | 地点 | 2022-11-08 |
2个 | 时间表 (11/10/22) | 时间表 | 2022-11-10 |
3个 | 测试 (12/09/22) | 测试 | 2022-12-09 |
4个 | 付款不正确 (9/10/22) | 付款错误 | 2022-09-10 |
5个 | 员工 (11/9/22) | 员工 | 2022-11-09 |
6个 | 授权 | 授权 | 无效的 |
7 | 不活跃的客户 | 不活跃的客户 | 无效的 |
8个 | 活跃客户 (07/22/2022) | 活跃客户 | 2022-07-22 |
9 | 测试 (09/09/22) | 测试 | 2022-09-09 |
10 | 时间表 | 时间表 | 无效的 |
我能够拆分参考列,但是找不到删除“(”和“)”并将其转换为标准日期格式的方法。 甚至可以按照我需要的方式转换,因为日期信息来自手动用户输入,因此 2022-09-08 可以以多种方式存在,例如:09/08/2022、09/08/22、09 /8/22、9/8/2022 和任何其他可能的方式。
SELECT
p.*
,SUBSTRING(p.Reference, 1, CASE CHARINDEX('(', p.Reference)
WHEN 0
THEN LEN(p.Reference)
ELSE CHARINDEX('(', p.Reference) - 1
END) AS Type
,SUBSTRING(p.Reference, CASE CHARINDEX('(', p.Reference)
WHEN 0
THEN LEN(p.Reference) + 1
ELSE CHARINDEX('(', p.Reference) + 0
END, 1000) AS Date
FROM Report AS p
ID | 参考 | 类型 | 日期 |
---|---|---|---|
1个 | 位置 (11/8/22) | 地点 | (11/8/22) |
2个 | 时间表 (11/10/22) | 时间表 | (11/10/22) |
3个 | 测试 (12/09/22) | 测试 | (12/09/22) |
4个 | 付款不正确 (9/10/22) | 付款错误 | (9/10/22) |
5个 | 员工 (11/9/22) | 员工 | (11/9/22) |
6个 | 授权 | 授权 | |
7 | 不活跃的客户 | 不活跃的客户 | |
8个 | 活跃客户 (07/22/2022) | 活跃客户 | (07/22/2022) |
9 | 测试 (09/09/22) | 测试 | (09/09/22) |
10 | 时间表 | 时间表 |
SELECT Id, Reference,
MAX(CAST(CASE CHARINDEX(')', value)
WHEN 0 THEN NULL
ELSE REPLACE(value, ')', '')
END AS DATE)) AS TheDate
FROM Report
OUTER APPLY STRING_SPLIT(Reference, '(')
GROUP BY Id, Reference;
正如您所看到的那样,您的表通过将非原子值放入列中而违反了第一范式(1FN)......那么这不是关系数据库,而是在过去接近 CoBOL 文件的东西......
然后查询困难,性能会很差。 您最好规范化您的数据库!
你的数据
declare @a table
(Id INT, Reference VARCHAR(100));
INSERT INTO @a
VALUES
(1, 'Location (11/8/22)'),
(2, 'Timesheet (11/10/22)'),
(3, 'TESTING (12/09/22)'),
(4, 'Incorrect Payment (9/10/22)'),
(5, 'Employee (11/9/22)'),
(6, 'Authorization'),
(7, 'Inactive Client'),
(8, 'Active Client (07/22/2022)'),
(9, 'TESTING (09/09/22)'),
(10, 'Timesheet')
您应该使用Substring
和Charindex
来识别()
和 LIKE 和 IIF 运算符,如果值没有()
,则日期的值为 null
SELECT id,
reference,
IIF(reference LIKE '%(%', Substring(reference, 0,
Charindex('(', reference)),
reference) as Type,
IIF(reference LIKE '%(%', Substring(reference, Charindex('(', reference)
+ 1,
Charindex(')', reference)
- Charindex('(', reference)
- 1), NULL) AS Date
FROM @a
;with cte as(
SELECT
p.id,
p.reference
,SUBSTRING(p.Reference, 1, CASE CHARINDEX('(', p.Reference)
WHEN 0
THEN LEN(p.Reference)
ELSE CHARINDEX('(', p.Reference) - 1
END) AS Type
,REPLACE(SUBSTRING(p.Reference, CASE CHARINDEX('(', p.Reference)
WHEN 0
THEN LEN(p.Reference) + 1
ELSE CHARINDEX('(', p.Reference) + 1
END, 1000),')','') AS Date1
FROM #Report AS p)
select *, CASE WHEN date1 IS NULL OR date1 = '' THEN NULL ELSE CAST(date1 AS DATE) END from cte
您可以尝试使用STRING_SPLIT函数,如下所示
WITH split_ref As(
SELECT R.Id, R.Reference, SP.value, SP.ordinal
FROM Report R
CROSS APPLY STRING_SPLIT(Reference, '(', 1) AS SP
)
SELECT Id, Reference,
MAX(CASE ordinal WHEN 1 THEN value END) AS Type,
MAX(CASE ordinal WHEN 2 THEN TRY_CAST(REPLACE(value, ')', '') AS DATE) END) AS [Date]
FROM split_ref
GROUP BY Id, Reference
ORDER BY Id
对于不支持序号的 SQL Server 版本,请尝试以下操作:
WITH split_ref As(
SELECT R.Id, R.Reference, SP.value,
CASE WHEN SP.value LIKE '%)' THEN 2 ELSE 1 END AS ordinal
FROM Report R
CROSS APPLY STRING_SPLIT(Reference, '(') AS SP
)
SELECT Id, Reference,
MAX(CASE ordinal WHEN 1 THEN value END) AS Type,
MAX(CASE ordinal WHEN 2 THEN TRY_CAST(REPLACE(value, ')', '') AS DATE) END) AS [Date]
FROM split_ref
GROUP BY Id, Reference
ORDER BY Id
看演示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.