2010-09-23 176 views
4

我有两个“日期”字段,我需要加入的。比较两个日期(非标准格式的varchar和日期)SQL最快的方式

首先是格式yyyy-mm-dd hh:mm:ss

第二正常日期时间为varchar(8)在红头继子女格式mmddyyyy

现在,因为没有简单的方法来此得到痛苦转换为相应的类型。有一种内置格式,即yyyymmdd,但与varchar格式不匹配。

有两条路我可以看到:

declare @normal_date as datetime; 
declare @hated_date as varchar(8); 

set @normal_date='1974-11-01 00:00:00.000' 
set @hated_date='11011974' 

--cast to date time with string splits 
select @normal_date 
where CONVERT(datetime, RIGHT(@hated_date,4)+LEFT(@hated_date,2)+SUBSTRING(@hated_date,3,2))[email protected]_date 

--convert normal date to ackward format 
select @normal_date 
     where REPLACE(CONVERT(varchar(10),@normal_date,101), '/','')[email protected]_date 

哪个更好?或者,还有更好的方法?

编辑,以显示成本

--Operator cost (39%) 
CONVERT(datetime, RIGHT(@hated_date,4)+LEFT(@hated_date,2)+SUBSTRING(@hated_date,3,2))[email protected]_date 

--Operator cost (57%) 
REPLACE(CONVERT(varchar(10),@normal_date,101), '/','')[email protected]_date 

--Operator cost (46%) 
cast(stuff(stuff(@hated_date, 3,0, '/'),6,0,'/') as datetime)[email protected]_date 

--Operator cost (47%) 
RIGHT(@hated_date, 4) + LEFT(@hated_date, 4)[email protected]_date 
+0

来自执行计划的运营商成本毫无意义。您需要使用'SET STATISTICS IO ON'运行每一百万次并进行比较。我想你会发现其中大部分都差不多。 – ErikE 2010-09-24 00:38:23

回答

5

这为yyyymmdd没有?

RIGHT(@hated_date, 4) + LEFT(@hated_date, 4) 

所以,你的脚本变得

declare @normal_date as datetime; 
declare @hated_date as varchar(8); 

set @normal_date='1974-11-01 00:00:00.000' 
set @hated_date='11011974' 

--SELECT @hated_date = RIGHT(@hated_date, 4) + LEFT(@hated_date, 4)) 

select 'hurrah' WHERE @normal_date = RIGHT(@hated_date, 4) + LEFT(@hated_date, 4) 
+0

我已测试过您的方法的性能。 – 2010-09-23 19:51:32

+0

@Denis Valeev:你是在桌子上还是在上面的一条线上测试过的? – gbn 2010-09-23 19:56:57

+1

看到我的答案;你应该读它。 :) – 2010-09-23 20:00:41

2

试试这个:

select cast(stuff(stuff('11011974', 3,0, '/'),6,0,'/') as datetime) 

更新

alt text

+0

您可能希望在查询之前添加'set dateformat mdy'。 – 2010-09-23 19:13:08

+0

有效,但它与其他人一样。我会说,“讨厌”的格式是记录少的格式。 – Nix 2010-09-23 19:28:12

+1

@Nix你如何衡量不同方法的性能?运行在生产? – 2010-09-23 19:30:20

2

另一种方法是这样的:

MONTH(@normal_date)*1000000 + DAY(@normal_date)*10000 + YEAR(@normal_date) 
= 
CAST(@hated_date AS INT) 

一两件事:它是更精确的比较实际的执行成本,而不是依靠优化的估计。

+0

似乎你的方法是最快的根据我的结果。这当然有些偏见,这需要在Nix的生产服务器上证明是最终的说法。 – 2010-09-23 20:14:37

+0

我不会说“更精确”,因为在这种情况下,执行计划成本几乎毫无意义。我会说“唯一的方法”。 – ErikE 2010-09-24 00:40:54

2

建议你要么修复列是日期时间或日期时间列添加到表中的数据转换,使您只有在输入的数据(一旦当然对现有数据)有一次做这种转换这甚至可能是一个计算列。这不是你想在选择语句中做的事情。如果需要的话,在两个队友的每个可能的日期内创建一个日期转换表,如果表不能更改,则加入到它。

您还可能要检查,以确保有在那里它总是在比日期时间之外的数据类型存储日期的可能性不存在无效的日期。

+0

'如果需要的话,在两个同伴的每一个可能的日期都创建一个日期转换表,如果表不能改变,就加入它。'你确定这会比简单的字符串操作更快吗? – 2010-09-23 20:33:19

+0

如果它被索引,我会期望它会更快,但你将不得不测试。这可能取决于涉及的记录数量。转换速度通常较慢。但修复数据库结构是所有的最佳选择。它可以很容易地进行比较,这使得输入不是日期的数据变得不可能,而且它还可以使您在需要进行数据运算的其他查询中也更容易。 – HLGEM 2010-09-23 21:03:03

+0

无法更改表格。我很想...不知道为什么你会用一个格式不正确的“varchar”日期。 – Nix 2010-09-24 00:52:25