簡體   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