2010-09-23 170 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