SQL Server条件顺序依据

时间:2011-06-29 16:23:00

标签: sql sql-server stored-procedures

我在SQL Server 2005中有一个SQL查询,当我包含条件顺序时,它会破坏。当我删除订单时,查询有效。当我通过条件明确地写顺序时(例如,通过p.Description命令),它可以工作。当我包含条件顺序时,我得到错误,

'Conversion failed when converting character string to smalldatetime data type'

SQL Server没有告诉我哪行代码导致了这个错误。我想知道如何解决这个问题,以便我可以使用条件订单或解决哪一列在转换中失败。

declare @SearchTerm nvarchar(255)
declare @SortBy nvarchar(255)
declare @Months int
declare @VendorID int
declare @ProductID int

set @SearchTerm = 'focus'
set @SortBy = 'product'
set @Months = 3
set @VendorID = null
set @ProductID = null

-- This makes it so the @Month will filter by n number of months ago.
declare @PreviousMonths datetime
if @Months is null
    begin
        set @PreviousMonths = 24
    end
else
    begin
        set @PreviousMonths = DateAdd(month, -@Months, GetDate())
    end

select
    a.dsAlertID as AlertID,
    a.ProductID,
    v.VendorID,
    p.Description as ProductName,
    v.LongName as VendorName,
    a.Introduction,
    a.Writeup,
    a.DateAdded 
from
    ev_ds_Alerts a
left outer join
    tblProducts p on a.ProductID = p.ProductID
left outer join
    tblVendors v on v.VendorID = p.VendorID
where
    ( @SearchTerm is null or ( a.Writeup like '% ' + @SearchTerm + '%' or a.Introduction like '% ' + @SearchTerm + '%') )
    and (( @Months is null ) or ( @Months is not null and a.DateAdded >= @PreviousMonths))
    and (( @VendorID is null ) or ( @VendorID is not null and v.VendorID = @VendorID ))
    and (( @ProductID is null ) or ( @ProductID is not null and p.ProductID = @ProductID ))
order by
    case @SortBy
        when 'product' then p.Description
        when 'vendor' then v.LongName
        else a.DateAdded
    end

-- order by p.Description or v.LongName works when explicitly writing them out!

5 个答案:

答案 0 :(得分:16)

根据上一个答案,尝试:

order by
    case @SortBy
        when 'product' then p.Description
        when 'vendor' then v.LongName
        else convert(VARCHAR(25),a.DateAdded,20)

这应该可以为您提供所需的排序,因为它会格式化日期字符串yyyy-mm-dd hh:mm:ss。

答案 1 :(得分:12)

您可以为每种数据类型使用一种情况:

order by
  case @SortBy
    when 'product' then p.Description
    when 'vendor' then v.LongName
    else ''
  end,
  case @SortBy
    when 'added' then a.DateAdded
    else '1980-01-01'
  end

答案 2 :(得分:6)

CASE中使用ORDER BY表达式时 - 返回的数据类型必须始终相同。

你不能选择你想要的东西 - INT,DATETIME,VARCHAR等 - 而不使用动态SQL或某种形式的决策逻辑(IE:IF)来突破不同的查询。 / p>

在此示例中,您可以使用CAST / CONVERT将DATETIME数据类型更改为适当的VARCHAR。但除非您知道为什么问题正在发生,否则您将来可能会再次这样做。

答案 3 :(得分:1)

将忽略要排序的列列表中的NULL,因此您可以按类型拆分它们;

ORDER BY
    CASE 
       WHEN @SortBy = 'product' THEN p.Description 
       WHEN @SortBy = 'vendor' THEN v.LongName 
    END
    ,
    CASE WHEN @SortBy NOT IN ('product', 'vendor') THEN cda.StartDate END   

对于最后的其他事情有点难看,如果可以,那就更好了;

 CASE WHEN @SortBy = '' THEN cda.StartDate END    

答案 4 :(得分:0)

如果您关心性能,可能需要采用不同的方法: 1.将您的选择内容包装在内联TVF中 2.使用两个不同的SELECT,以便他们可以获得两个不同的计划,可能比您现在获得的通用的“一刀切”计划更有效:

IF @SortBy='product' BEGIN
  SELECT AlertID,
(snip)
  FROM MyTvf
  ORDER BY Description ;
  RETURN @@ERROR ;
END 

IF @SortBy='Vendor' BEGIN
  SELECT AlertID,
(snip)
  FROM MyTvf
  ORDER BY LongName ;
  RETURN @@ERROR ;
END