【问题标题】:Microsoft SQL Case statement not working in Order By statementMicrosoft SQL Case 语句在 Order By 语句中不起作用
【发布时间】:2019-07-31 07:44:52
【问题描述】:

我有一个数据库列,它用作产品变体的分组,它不在第一范式中。我们不需要将宽度、高度和测量值放在单独的列中。

我们在这一数据库列中有各种属性,例如,产品尺寸如 1200*400mm,有时米如 1m,甚至颜色如 红色,蓝色和绿色。

问题是 CASE 语句被忽略,SQL 试图在 Case 语句中将 Black 转换为 Int。

目前,代码需要对 SQL 现在所做的大小正确排序。当它获取仅具有颜色属性的产品并且 CASE 语句在 Order By 部分附近被忽略时,就会出现问题。

我创建了这个 SQL Fiddle 来展示带有尺寸和颜色的 DB 列。 http://sqlfiddle.com/#!18/4e58e/1

这是我当前的 SQL:

  DECLARE @StockID int = 684

  DECLARE @VariationParent int = (SELECT TOP 1 StockParent_ParentId FROM 
  StockVariations SV INNER JOIN FinGoodsParent FGP ON FGP.Id = 
  SV.StockParent_ChildId WHERE StockParent_ChildId = @StockID AND 
  SV.IsDeleted = 0 AND FGP.IsDeleted = 0 AND FGP.Publish = 1) 

  SELECT  AV.ID, AV.AttrValue, AV.AttributeTypes_Id 'AttributeTypeID', 
  CAST(CASE WHEN SA.StockParent_Id = @StockID THEN 1 ELSE 0 END as BIT) 
  'IsDefault' 
  FROM AttributeTypes AT 
  INNER JOIN AttributeValues AV ON AV.AttributeTypes_Id = AT.Id 
  INNER JOIN StockParent_AttributeValues SA on SA.AttributeValue_Id = AV.Id 
  INNER JOIN FinGoodsParent FGP ON FGP.Id = SA.StockParent_Id AND 
  FGP.IsDeleted = 0 AND FGP.Publish = 1
  WHERE SA.StockParent_Id IN (SELECT SV.StockParent_ChildId FROM 
  StockVariations SV INNER JOIN FinGoodsParent FGP ON FGP.Id = 
  SV.StockParent_ChildId AND FGP.IsDeleted = 0 AND FGP.Publish = 1 WHERE 
  SV.StockParent_ParentId = @VariationParent AND SV.IsDeleted = 0) 
  AND SA.IsDeleted = 0 AND AT.IsDeleted = 0 AND AV.IsDeleted = 0
  ORDER BY 
  CASE WHEN (CHARINDEX('*', AV.AttrValue) > 0 
  AND CHARINDEX('mm', AV.AttrValue) > 0)
  THEN
  CONVERT(int, (select top 1 value from STRING_SPLIT(AV.AttrValue, '*'))) * 
  CONVERT(int, (select top 1 LEFT(value, LEN(value) - 2) from 
  STRING_SPLIT(AV.AttrValue, '*') where value LIKE '%mm'))  

  ELSE

  AV.AttrValue

  END

  ASC

这是我在尝试获取仅具有颜色属性的产品并使用 CASE 语句按属性名称对其进行排序时遇到的错误。

所以基本上我得到了这个 SQL 代码来从 How to match a width and height size with a Regex expression and use Sort By in SQL or C# to build a drop-down? 进行排序

我添加了 CASE 语句来尝试仅在列中有星号 * 和 mm 时进行排序,否则,我只想在列包含例如 red 或黑色而不是数字。

更新

我已经更新了 SQL Fiddle,因为数据输出只能是尺寸或颜色。因此,我为此示例添加了一个带有类型的附加列。在 WHERE 子句附近检索数据的 SQL 应该是 0(尺寸)或 1(仅颜色),并且 SQL 应该仍然能够正常工作并正确排序尺寸的输出。

http://sqlfiddle.com/#!18/56b3e/1

【问题讨论】:

    标签: sql-server sorting case


    【解决方案1】:

    说明:

    考虑以下几点:

    • CASE 评估条件列表和returns 类型集中的最高优先级类型。在您的情况下,您有 intvarchar 作为可能的返回值,这解释了您的 Conversion failed when converting the varchar value 'Black' to data type int 错误。
    • 不要使用SELECT TOP 1 FROM STRING_SPLIT(),因为STRING_SPLIT() 不保证拆分的子字符串的顺序与它们在原始字符串中的位置相匹配。在您的情况下,您可以尝试使用带有LEFTRIGHTCHARINDEX 函数的简单字符串解析。之后,您需要将计算结果转换为varchar

    示例:

    表:

    CREATE TABLE attributes
        ([AttrValue] varchar(13))
    ;
    
    INSERT INTO attributes
        ([AttrValue])
    VALUES
        ('900*900mm'),
        ('1200*900mm'),
        ('1200*1200mm'),
        ('1200*6000mm'),
        ('1500*3000mm'),
        ('Red'),
        ('Green'),
        ('Black'),
        ('Purple')
    ;
    

    声明:

    SELECT
      AttrValue
    FROM
      attributes
    ORDER BY 
       CASE 
          WHEN (CHARINDEX('*', AttrValue) > 0 AND CHARINDEX('mm', AttrValue) > 0) THEN
             RIGHT(
                REPLICATE('0', 13) +
                CONVERT(
                   varchar(13),
                   CONVERT(int, LEFT(REPLACE(AttrValue, 'mm', ''), CHARINDEX('*', REPLACE(AttrValue, 'mm', '')) - 1)) *
                   CONVERT(int, RIGHT(REPLACE(AttrValue, 'mm', ''), LEN(REPLACE(AttrValue, 'mm', '')) - CHARINDEX('*', REPLACE(AttrValue, 'mm', ''))))
                ),
                13
             )   
          ELSE AttrValue
      END ASC
    

    输出:

    --------------
    AttrValue
    --------------
    900*900mm
    1200*900mm
    1200*1200mm
    1500*3000mm
    1200*6000mm
    Black
    Green
    Purple
    Red
    

    【讨论】:

    • 感谢您的回答。我已经更新了我的问题和上面的小提琴。输出应仅检索尺寸或颜色。出于某种原因,在 SQL Fiddle 中,数字的顺序看起来不正确。它应该从最小的数字到最高的数字,颜色应该从 A - Z。
    • @Tig7r 我的错误,结果应该用0 填充。如果您有额外的attType 归档,那么您不需要将计算转换为varchar(12)``CASE 查看更新的示例。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多