繁体   English   中英

SQL 服务器有条件订购者

[英]SQL Server Conditional Order By

我在 SQL Server 2005 中有一个 SQL 查询,当我包含条件订单时,该查询会中断。 当我删除订单时,查询有效。 当我明确地按条件编写顺序(例如,按 p.Description 顺序)时,它可以工作。 当我包含条件顺序时,我收到错误,

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

SQL 服务器没有向我显示导致此错误的代码行。 我想知道如何解决这个问题,以便我可以使用条件顺序或排除转换中哪个列失败。

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!

根据上一个答案,尝试:

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。

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

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

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

如果不使用动态 SQL 或某种形式的决策逻辑 (IE: IF ) 来突破不同的查询,您就无法挑选您想要的东西——INT、DATETIME、VARCHAR 等。

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

列列表中的 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    

如果您关心性能,您可能需要一种不同的方法: 1. 将 select 包装在一个内联 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 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM