【问题标题】:'Order By ' SQL issue (out of range date/time value)'Order By' SQL 问题(超出范围的日期/时间值)
【发布时间】:2010-12-02 12:57:05
【问题描述】:

我对以下查询有疑问:

SELECT 
    Consignments.LegacyID, 
    Consignments.TripDate,
    Consignments.CollectionName, 
    CASE 
        WHEN Sage2.InvoiceSummaryType = 'HT' THEN DeliveryTown 
        ELSE DeliveryName + ', ' + DeliveryTown + ', ' + DeliveryPostCode END AS 'DeliveryName', 
    Consignments.Pallets, 
    Consignments.Weight, 
    Consignments.BaseRate, 
    Consignments.FuelSurcharge, 
    Consignments.AdditionalCharges, 
    Consignments.BaseRate * Consignments.Quantity AS 'InvoiceValue', 
    Consignments.InvoiceNumber, 
    Consignments.Customer 
FROM 
    Consignments 

    INNER JOIN SageAccount 
        ON Consignments.Customer = SageAccount.LegacyID 
        AND SageAccount.Customer = 'true' 

    LEFT OUTER JOIN SageAccount AS Sage2 
        ON SageAccount.InvoiceAccount = Sage2.LegacyID 
WHERE 
    (Sage2.Customer = 'true') 
    AND (Consignments.Customer = @Customer) 
    AND (Consignments.InvoiceNumber IS NOT NULL) 
    OR (Sage2.Customer = 'true') 
    AND (Consignments.InvoiceNumber IS NOT NULL) 
    AND (Sage2.InvoiceAccount = @Customer)  

ORDER BY 
    CASE 
        WHEN Sage2.InvoiceSummaryType = 'HR' THEN TripDate  
        WHEN Sage2.InvoiceSummaryType = 'HS' THEN Consignments.LegacyID 
    END

由于某种原因,它一直给我以下错误:

The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value order by

但仅当它尝试Order By TripDate 时,即当案例“HR”发生时。 TripDate 是一个“日期时间字段”。

有什么想法吗?

【问题讨论】:

    标签: sql-server tsql datetime


    【解决方案1】:

    刚刚再次阅读了这个问题,如果没有看到执行计划,我无法解释你得到的具体症状(我原以为HS 会导致问题)。一般来说,虽然你应该避免在CASE 表达式中混合数据类型,因为它根本不起作用select case when 1=0 then GETDATE() else 'foo' end 将失败,因为它试图将字符串转换为datetime

    ORDER BY
             CASE
                      WHEN Sage2.InvoiceSummaryType = 'HR'
                      THEN TripDate
                      WHEN Sage2.InvoiceSummaryType = 'HS'
                      THEN Consignments.LegacyID
             END
    

    要解决这个问题,您可以使用cast(TripDate as float) - 假设(可能不正确)ID 字段是数字或使用此成语。

    ORDER BY
             CASE
                      WHEN Sage2.InvoiceSummaryType = 'HR'
                      THEN TripDate
                      ELSE NULL
             END,
             CASE
                      WHEN Sage2.InvoiceSummaryType = 'HS'
                      THEN Consignments.LegacyID
                      ELSE NULL
             END
    

    您需要检查执行计划以进行性能比较。

    【讨论】:

    • 我猜你的怀疑在某种程度上是正确的。在集合包含两种数据之前,可能没有问题。之后,您可能会说它们两者都会导致问题,或者说它们都不会导致问题,只是将它们一起使用会导致错误。实际上,正如您所说,在比较中使用它们之前,请避免混合数据类型或将它们强制为某种常见类型。 +1
    • 谢谢哥们,我试了你的第二个查询,结果很完美。
    【解决方案2】:

    您在 THEN TripDate 之后不需要“END”吗?

    【讨论】:

      【解决方案3】:

      CASE 语句中的所有选项都必须是相同的数据类型。 LegacyID 是一个字符吗?

      你会在任何地方遇到这个问题,而不仅仅是按顺序排列。如果您执行 CASE WHEN 'x' THEN (some int) WHEN 'y' THEN (some date) 并且 SQL 无法对所有值进行隐式转换,那么您就完蛋了。

      【讨论】:

        【解决方案4】:

        如果您要进行大小写排序,则数据类型必须相互兼容。

        试试这个日期:

        Convert(int, TripDate , 112) 
        

        112 的格式将为您提供 yyyymmdd,这对于按日期作为整数进行排序非常有用。使用 1 - [日期] 进行降序。

        这是假设 LegacyID 是一个整数。否则,您可以尝试将日期转换为 SQL_VARIANT 类型

        【讨论】:

        • 知道SQL_VARIANT 的排序方式吗?它是否进行二进制排序?如果是这样,那可能不合适。
        • 我不确定。您始终可以如上所述转换为整数,然后将大小写转换为 sql_variant。 msdn.microsoft.com/en-us/library/ms173829.aspx
        猜你喜欢
        • 2019-02-20
        • 2010-12-05
        • 1970-01-01
        • 2011-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多