2013-03-18 4 views
1

В таком случае у меня есть еще один. Это то же самое, что и раньше. Результаты не были тем, что мне нужно, поэтому вернулись к чертежной доске. Одинаковые:TSQL date сравнение возвращает ошибочный текст центральная ошибка

SQL Server 2005 || Excel 2007 || Студия SQL Management 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. Изменение даты на датуpart функции только потянув год. мы знаем, что должны возвращать 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], работает нормально.

помогите мне, Оби, любой, ты моя единственная надежда. Заранее спасибо.

+0

Плохие планы выполнения могут иногда иметь интересные побочные эффекты. Отправьте план выполнения этого запроса. – GSerg

+0

Планы выполнения не работают или не создают ничего для плохого кода. когда я выключить NOCOUNT, я получаю это: это ошибка компиляции (13 строк (ы) пострадавших) (1 ряд (ы) пострадавших) (6620 строк (ы) пострадавших) (1 ряд (s)) Msg 402, уровень 16, состояние 1, строка 146 Текст типов данных и varchar несовместимы в равном оператору. это ошибка компиляции –

+0

Я думаю, нам понадобится больше контекста (где используется CASE, а также типы данных всех столбцов), чтобы выяснить, почему вы получаете ошибку. Но ваше выражение просто похоже на тестирование: @ counter = 0. – GilM

ответ

1

Я думаю, что проблема не в том, что часть вашего сазе, я думаю, что это:

when frequency = 'OneTime' 

, так как столбец частоты имеет тип данных текст.

Вы можете попробовать:

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

или что-то.

+0

, вы были абсолютно правы. Я действительно искал в Интернете ошибку, и нашел некоторые вещи, которые привели меня в правильном направлении. чтобы проверить, я прокомментировал заявление дела «OneTime», но оставил внутренний, и он сработал. странно, я попытался изменить тип данных при создании таблицы temp, и это не исправить. он работает сейчас. Спасибо. если бы только ловушка ошибки была лучше, было бы легче отследить. также странно, что проверка работала так, как это было без внутреннего заявления. Я вернулся, чтобы опубликовать решение, но вы избили меня до него :) –

Смежные вопросы