我有一个包含两个日期的列,即开始日期和结束日期
+---------------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)+
+--------------------------------------------+
答案 0 :(得分:0)
即使名称部分可以更改长度,您仍然可以使用CHARINDEX和SUBSTRING,如下所示:
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;
结果: