繁体   English   中英

拆分列,然后将不同的日期类型转换为标准日期格式 (YYYY-MM-DD) - SQL Server

[英]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')

您应该使用SubstringCharindex来识别()和 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM