将一个列中的两个日期拆分为两个不同的列

时间:2016-09-28 16:00:41

标签: sql-server

我有一个包含两个日期的列,即开始日期和结束日期

+---------------StartAndEndDate--------------+
+      JayZ -  (08/21/2016 - 08/22/2016)     +
+--------------------------------------------+

根据前面的例子,上面只有一列。如何分割给定日期并将其存储在两个不同的列中。

预期输出应为

+----StartDate----+----EndDate----+
+   08/21/2016    +  08/22/2016   +
+-----------------+---------------+

仅供参考:之前的字符(随机长度可以更改。对于实例

+---------------StartAndEndDate--------------+
+   JayZ -  (08/21/2016 - 08/22/2016)        +
+   JohnSmith -  (09/11/2016 - 09/20/2016)   +
+   Rick from NY -  (08/21/2016 - 08/22/2016)+
+--------------------------------------------+

2 个答案:

答案 0 :(得分:0)

即使名称部分可以更改长度,您仍然可以使用CHARINDEXSUBSTRING,如下所示:

CREATE TABLE #Source 
(
    StartAndEndDate nvarchar(1000)
);

INSERT INTO #Source (StartAndEndDate)
VALUES
    ('JayZ -  (08/21/2016 - 08/22/2016)'),
    ('JohnSmith -  (09/11/2016 - 09/20/2016)'),
    ('Rick from NY -  (08/21/2016 - 08/22/2016)');

SELECT
    *
FROM
    #Source;

SELECT
    SUBSTRING(StartAndEndDate, CHARINDEX('-', StartAndEndDate) + 4, 10) as StartDate,
    SUBSTRING(StartAndEndDate, CHARINDEX('-', StartAndEndDate) + 17, 10) as EndDate
INTO 
    #Destination
FROM
    #Source

SELECT
    *
FROM
    #Destination;

DROP TABLE #Source;
DROP TABLE #Destination;

唯一需要注意的是该名称不能包含连字符。另一种方法是从字符串的末尾开始计算:

CREATE TABLE #Source 
(
    StartAndEndDate nvarchar(1000)
);

INSERT INTO #Source (StartAndEndDate)
VALUES
    ('JayZ -  (08/21/2016 - 08/22/2016)'),
    ('JohnSmith -  (09/11/2016 - 09/20/2016)'),
    ('Rick from NY -  (08/21/2016 - 08/22/2016)');

SELECT
    *
FROM
    #Source;

SELECT
    SUBSTRING(StartAndEndDate, LEN(StartAndEndDate) - 23, 10) as StartDate,
    SUBSTRING(StartAndEndDate, LEN(StartAndEndDate) - 10, 10) as EndDate
INTO 
    #Destination
FROM
    #Source

SELECT
    *
FROM
    #Destination;

DROP TABLE #Source;
DROP TABLE #Destination;

<强>性能

在对性能进行一些评论之后,我在非常完整的数据库上运行了一个非常粗略的性能测试。在100,000行上拆分字段需要30到50毫秒。基本上它足够快,我担心分辨率SYSDATETIME()可以管理。在繁忙的数据库中,事情可能会变慢,但是读取,写入和索引将是问题,而不是字符串拆分。我使用的代码如下:

SET NOCOUNT ON;

CREATE TABLE #Source 
(
    StartAndEndDate nvarchar(1000)
);

DECLARE 
    @i int = 100000,
    @l int = 0;

WHILE (@i > 0)
BEGIN
    SET @l = RAND() * 20;

    INSERT INTO #Source (StartAndEndDate)
    VALUES
        (SUBSTRING('XXXXXXXXXXXXXXXXXXXXXX', 0, @l) + ' -  (08/21/2016 - 08/22/2016)' );

    SET @i = @i - 1;
END

SELECT
    *
FROM
    #Source;

DECLARE @Start DateTime = SYSDATETIME();

SELECT
    SUBSTRING(StartAndEndDate, LEN(StartAndEndDate) - 23, 10) as StartDate,
    SUBSTRING(StartAndEndDate, LEN(StartAndEndDate) - 10, 10) as EndDate
INTO 
    #Destination
FROM
    #Source

PRINT 'Time Taken ' + CONVERT(nvarchar(50), DATEDIFF(ms, @Start, SYSDATETIME())) + 'ms';    

SELECT
    *
FROM
    #Destination;

DROP TABLE #Source;
DROP TABLE #Destination; 

答案 1 :(得分:0)

这可能有所帮助:

CREATE TABLE [dbo].[Dates]
    (
      [ID] [INT] IDENTITY(1, 1)
                 NOT NULL ,
      [StartAndEndDate] [NVARCHAR](100) NOT NULL 
    ); 


INSERT  INTO [dbo].[Dates]
        ( StartAndEndDate )
VALUES  ( 'JayZ -  (08/21/2016 - 08/22/2016)' ),
        ( 'JohnSmith -  (09/11/2016 - 09/20/2016)' ),
        ( 'Rick from NY -  (08/21/2016 - 08/22/2016)' );

WITH    CTE
          AS ( SELECT   Name = SUBSTRING(StartAndEndDate, 0,
                                         CHARINDEX('-', StartAndEndDate)) ,
                        StartAndEndDate = SUBSTRING(StartAndEndDate,
                                                    CHARINDEX('(',
                                                              StartAndEndDate)
                                                    + 1,
                                                    CHARINDEX(')',
                                                              StartAndEndDate)
                                                    - CHARINDEX('(',
                                                              StartAndEndDate)
                                                    - 1)
               FROM     dbo.[Dates]
             )
    SELECT  Name ,
            StartDate = RTRIM(LTRIM(SUBSTRING(StartAndEndDate, 0,
                                              LEN(StartAndEndDate)
                                              - CHARINDEX('-', StartAndEndDate)))) ,
            EndDate = RTRIM(LTRIM(SUBSTRING(StartAndEndDate,
                                            CHARINDEX('-', StartAndEndDate)
                                            + 1,
                                            LEN(StartAndEndDate)
                                            - CHARINDEX('-', StartAndEndDate)
                                            + 1)))
    FROM    CTE;

结果:

enter image description here