2013-03-18 30 views
1

那麼,我有另一個。這與我之前的工作流程相同。結果不是我所需要的,因此回到了製圖板。系統是一樣的:TSQL日期比較返回erroneus文本中心錯誤

SQL Server 2005 || Excel 2007 || SQL Management Studio 2008R2

我在比較兩個日期時遇到問題。 SSMS拋出的錯誤是毫無意義的。下面是代碼:

declare @calendar_start char(8) 
declare @years int 

set @calendar_start = '20130101' 
set @years = 1 

---------------------------------------------------------------------------- 
-- standard declaration stuff. - 
---------------------------------------------------------------------------- 

-- for ease of entry, I convert the start timeto a real time --------------- 
---------------------------------------------------------------------------- 
declare @startdate datetime 
set  @startdate = CONVERT (datetime, @calendar_start, 112) 

-- to calculate the end of the forecast, I use the start date and add the -- 
-- provided number of year ------------------------------------------------- 
---------------------------------------------------------------------------- 
declare @enddate datetime 
set  @enddate = dateadd(year,[email protected],@startdate) 
---------------------------------------------------------------------------- 

-- I need a variable to advance the plotting month. the plotting month is -- 
-- how I am going to spread out the project all year from a single date ---- 
---------------------------------------------------------------------------- 
declare @counter int 
set  @counter = 0 
---------------------------------------------------------------------------- 

---------------------------------------------------------------------------- 
-- this table will be used to have all the calendar dates by year-month ---- 
---------------------------------------------------------------------------- 
create table #calendar (calenderid char(6)) 

insert into #calendar 
    select 
     distinct left(calendarid,6) [yearmonth] 
    from 
     [cmdb_core].[dbo].[Calendar] 
    where 
     datevalue between @startdate and @enddate 
---------------------------------------------------------------------------- 

---------------------------------------------------------------------------- 
-- rather than hitting the database any number of times, I load the whole -- 
-- of the computed estimates table into memory. it is faster that way. ---- 
---------------------------------------------------------------------------- 
create table #baseline (
    [adjusted_ExpectedActionDt] datetime 
    ,[key] text 
    ,projectid text 
    ,projectnm text 
    ,ParentChaseProjectNo text 
    ,VersionTag text 
    ,itemid text 
    ,Qty int 
    ,ItemNotes text 
    ,CashflowType text 
    ,frequency text 
    ,UnitPrice float 
    ,[cost] float 
) 

insert into #baseline (
    [adjusted_ExpectedActionDt] 
    ,[key] 
    ,projectid 
    ,projectnm 
    ,ParentChaseProjectNo 
    ,VersionTag 
    ,itemid 
    ,Qty 
    ,ItemNotes 
    ,CashflowType 
    ,frequency 
    ,UnitPrice 
    ,[cost] 
) 
select 
    case 
     when (ExpectedActionDt is not null) 
      then ExpectedActionDt 
     when (IntegratedReleasePlanDt is not null) 
      then IntegratedReleasePlanDt 
     else 
      DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0) 
    end [adjusted_ExpectedActionDt] 
    ,cast(ModelEstimateId as nvarchar(max))+cast(BucketId as nvarchar(max))+cast(ItemNo as nvarchar(max)) [key] 
    ,projectid 
    ,projectnm 
    ,ParentChaseProjectNo 
    ,VersionTag 
    ,itemid 
    ,Qty 
    ,ItemNotes 
    ,CashflowType 
    ,frequency 
    ,UnitPrice 
    ,null [cost] 
from 
    estimate.ComputedEstimates 
where 
     [status] <> 'Hold' 
    and CostCategory <> 'Assembly' 
    and includeinforecast = 'Y' 
    and cashflowtype <> 'Notional' 
    and Qty <> 0 
    and case 
      when (ExpectedActionDt is not null) 
       then ExpectedActionDt 
      when (IntegratedReleasePlanDt is not null) 
       then IntegratedReleasePlanDt 
      else 
       DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0) 
     end between @startdate and @enddate 
-------------------------------------------------------------------------- 

-------------------------------------------------------------------------- 
-- we need a place to contain the results of the interation through the -- 
-- baseline temp table. the results table will be that. ------------------ 
-------------------------------------------------------------------------- 
create table #results (
    [adjusted_ExpectedActionDt] datetime 
    ,[plot_date] datetime 
    ,[key] text 
    ,projectid text 
    ,projectnm text 
    ,ParentChaseProjectNo text 
    ,VersionTag text 
    ,itemid text 
    ,Qty int 
    ,ItemNotes text 
    ,CashflowType text 
    ,frequency text 
    ,UnitPrice float 
    ,[cost] float 
) 

-- this loop is how we will build the results. it is governed by the ----- 
-- date. as I iterate through the loop, I incriment the plot date so ----- 
-- that I can show a project and it's costs over the range of dates ------ 
-- rather than only the month it goes into production -------------------- 
-------------------------------------------------------------------------- 
WHILE (@startdate <= @enddate) 
BEGIN 
insert into #results (
    [adjusted_ExpectedActionDt] 
    ,[plot_date] 
    ,[key] 
    ,projectid 
    ,projectnm 
    ,ParentChaseProjectNo 
    ,VersionTag 
    ,itemid 
    ,Qty 
    ,ItemNotes 
    ,CashflowType 
    ,frequency 
    ,UnitPrice 
    ,[cost] 
) 
select 
    [adjusted_ExpectedActionDt] 
    ,dateadd(month,[email protected],[adjusted_ExpectedActionDt]) 
    ,[key] 
    ,projectid 
    ,projectnm 
    ,ParentChaseProjectNo 
    ,VersionTag 
    ,itemid 
    ,Qty 
    ,ItemNotes 
    ,CashflowType 
    ,frequency 
    ,UnitPrice 
    ,case 
     when frequency = 'OneTime' 
      then 
--=====================================================================-- 
--===================== this is where the problem is ==================-- 
--=====================================================================--   
       case 
        when dateadd(mm, datediff(mm,0, [adjusted_ExpectedActionDt]), 0) = 
         dateadd(mm, datediff(mm,0, dateadd(month,[email protected],[adjusted_ExpectedActionDt])), 0) 
         then [Qty] 
        else 
         0 
       end 
--=====================================================================-- 
--=====================================================================-- 
     else 
      cast(round((UnitPrice*Qty)/12,0) as int) 
     end [cost] 
from #baseline 

set @counter = @counter+1 
set @startdate = dateadd(month,+1,@startdate) 
END 
-------------------------------------------------------------------------- 

-------------------------------------------------------------------------- 
-- now we have to return the results but it is not enough to just dump --- 
-- the table, I have to add a date that covers all month regardless of --- 
-- that month's presence in the results table. I use the calendar temp, -- 
-- which has those dates as a basis of the outer join -------------------- 
-------------------------------------------------------------------------- 

select 
    c.calenderid 
    ,r.[adjusted_ExpectedActionDt] 
    ,r.[plot_date] 
    ,r.[key] 
    ,r.projectid 
    ,r.projectnm 
    ,r.ParentChaseProjectNo 
    ,r.VersionTag 
    ,r.itemid 
    ,r.Qty 
    ,r.ItemNotes 
    ,r.CashflowType 
    ,r.frequency 
    ,r.UnitPrice 
    ,r.[cost] 
from 
    #calendar c 
    left outer join 
    #results r 
    on c.calenderid = cast(year(r.[adjusted_ExpectedActionDt])as char(4))+RIGHT('0'+ CONVERT(VARCHAR,month(r.[adjusted_ExpectedActionDt])),2) 
-------------------------------------------------------------------------- 
GO 

的問題是:

--=====================================================================-- 
--===================== this is where the problem is ==================-- 
--=====================================================================--   
       case 
        when dateadd(mm, datediff(mm,0, [adjusted_ExpectedActionDt]), 0) = 
         dateadd(mm, datediff(mm,0, dateadd(month,[email protected],[adjusted_ExpectedActionDt])), 0) 
         then [Qty] 
        else 
         0 
       end 
--=====================================================================-- 
--=====================================================================-- 

當我嘗試運行這段代碼,我得到以下錯誤:

Msg 402, Level 16, State 1, Line 149 
The data types text and varchar are incompatible in the equal to operator. 

這是最vexxing作爲比較是日期匹配而不是文本。 這個我試過了: 1.大量的網絡搜索 2.把case語句改成if語句,但是沒有得到正確的語法。 3.將日期更改爲datepart函數只拉年份。我們知道應該返回一個int 4.將比較結果改爲「1 = 1」,這個數字顯然是數字並且應該總是爲真 5.嘗試轉換爲連接文本(yyyymm) 6.與我們的SQL開發人員交談對此我不是冠軍,但希望是此項目:))

結束真是個奇怪的是,這個普通的代碼工作

select 
    dateadd(mm, datediff(mm,0, getdate()), 0) 
    ,dateadd(mm, datediff(mm,0, getdate()+60), 0) 
    ,case 
     when dateadd(mm, datediff(mm,0, getdate()), 0) = 
      dateadd(mm, datediff(mm,0, getdate()+60), 0) 
      then 'matches' 
     else 
      'different' 
    end 

信息的最後一點是,如果我的評論有問題的代碼只剩下[Qty]字段,它運行良好。

幫助我Obi - 任何人,你是我唯一的希望。先謝謝你。

+0

錯誤的執行計劃有時會產生有趣的副作用。請發佈該查詢的執行計劃。 – GSerg 2013-03-18 17:17:28

+0

執行計劃失敗或不會產生任何錯誤代碼。當我關掉NOCOUNT,我得到這個: 它是(受影響的13行(S))的編譯錯誤 (1行(S)的影響) (6620行(S)的影響) (1行( s)受影響) 消息402,級別16,狀態1,行146 數據類型text和varchar在等於運算符中不兼容。這是一個編譯錯誤 – 2013-03-18 17:56:15

+0

我想我們需要更多的上下文(使用CASE的地方,以及所有列的數據類型)來弄清楚爲什麼你會得到錯誤。但是,你的表達式似乎只是測試@ counter = 0。 – GilM 2013-03-18 18:15:47

回答

1

我覺得這個問題是不是你的CASE語句的一部分,我認爲這是:

when frequency = 'OneTime' 

因爲頻率列是數據類型的文本。

您可以試試:

when cast(frequency as varchar(20)) = 'OneTime' 

什麼的。

+0

你是絕對正確的。我專門在網上搜索了一些錯誤,發現了一些讓我朝着正確方向發展的東西。爲了測試,我評論了'OneTime'案例陳述,但留下了內部陳述,並且它工作。奇怪的是,我試圖在創建臨時表中更改數據類型,但沒有解決它。它正在工作。謝謝。如果只有錯誤陷阱更好,那麼追蹤起來會更容易。這也是奇怪的檢查工作,因爲它沒有內部的情況下的聲明。我回來發佈解決方案,但你擊敗了我:) – 2013-03-18 19:25:08