SQL 求助 - 计算除特殊情况外的所有序列号

SQL help - count all serialNumbers except those with specific cases

我需要帮助在 where 子句中编写 case 语句。

假设我们有一堆序列号存储在数据库中。 它们以一些字母为前缀来表示它们的组。

这是我需要完成的:

排除所有以 'GIU' 开头的序列号,除非某些条件适用:

例如。应包括 GIU930798246071,因为:以 GIU 开头 -> 15 个字符长 -> 6071 > 5000.

ex2。应该包括 GIU9307982410621,因为它以 GIU 开头 -> 16 个字符长 -> 10621 > 10000.

ex3。应排除 GIU930798243071,因为 15 个字符长 -> 最后 4 位数字 (3071) < 5000。

如果我想 运行 一个查询来计算这些结果,我试过:

select count(serialNum) 
FROM serialNumbers 
WHERE serialNum not like (
case when LEN(serialNum) = 15 and SUBSTRING(serialNum, 1, 3) = 'GIU' and RIGHT(serialNum, 4) < 5000 then 'GIU%' 
when LEN(serialNum) = 16 and SUBSTRING(serialNum, 1, 3) = 'GIU' and RIGHT(serialNum, 5) < 10000 then 'GIU%' end)

如果这些条件适用,我正在尝试将 case 语句的结果附加到 not like 语句中。

运行 查询 returns 为空,所以我知道部分情况会破坏整个查询。

此外,还有其他序列号以其他字母开头,它也应该计算在内。

我基本上只需要它来计算除这些特定情况下以 GIU 开头的序列号之外的所有序列号。

感谢任何帮助。

有时候事情可能比你想象的要简单。我重新安排了您的 WHERE 子句以匹配您在描述中提供的规格。我得到这样的东西。

select count(serialNum) 
FROM serialNumbers 
WHERE
  serialNum not like 'GIU%' or
  (LEN(serialNum) = 15 and CAST(RIGHT(serialNum, 4) AS INT) >= 5000) or
  (LEN(serialNum) = 16 and CAST(RIGHT(serialNum, 5) AS INT) >= 10000)

这有帮助吗?

请注意,我明确地将序列号的最后 4 或 5 位转换为整数。如果这些位置不是数字,我假设查询将失败。这种情况也有解决方案,但为了清楚起见,我在这里省略了它们。

编辑:

假设上述查询逻辑正确,还有另一种解决方案。

大于或等于 5000 的 4 位数字的形式为 5nnn6nnn7nnn8nnn9nnn。大于或等于 10000 的 5 位数字不以 0 开头。

在这些情况下使用 LIKE 模式匹配,您也可以使用以下查询:

select count(serialNum) 
FROM serialNumbers 
WHERE
  serialNum not like 'GIU%' or
  (LEN(serialNum) = 15 and serialNum like '%[56789]___') or
  (LEN(serialNum) = 16 and serialNum like '%[^0]____')

请注意,我在此处的 LIKE 模式中使用了下划线来匹配任何单个字符。我只是假设它们实际上是数字。

编辑 2:

对不起。重新阅读您的问题,我可能以错误的方式检查了最后一位数字。已修复。

因此,您可以做一个专栏来确认您正在寻找(或不寻找)什么。一旦你确认了,那就去做吧。通过稍微改变 Bart 提供的内容,您需要在条件中明确包含“GIU”

你不想要什么...

       ( left( serialNum, 3 ) = 'GIU'
   AND LEN(serialNum) = 15
   AND CAST(RIGHT(serialNum, 4) AS INT) < 5000 )

     OR  

       ( left( serialNum, 3 ) = 'GIU'
   AND LEN(serialNum) = 16
   AND CAST(RIGHT(serialNum, 5) AS INT) < 10000 )

因此,如果 where 子句是上述内容,您将只能获得排除领域中的那些。所以要反转这个,

WHERE NOT ( above condition1 or condition2 )

因此

   WHERE 
      NOT (
              ( left( serialNum, 3 ) = 'GIU'
          AND LEN(serialNum) = 15
          AND CAST(RIGHT(serialNum, 4) AS INT) < 5000 )
    
         OR  
    
              ( left( serialNum, 3 ) = 'GIU'
          AND LEN(serialNum) = 16
          AND CAST(RIGHT(serialNum, 5) AS INT) < 10000 )
        )