【问题标题】:SQL Server : Islands And GapsSQL Server:孤岛和差距
【发布时间】:2015-06-23 03:31:29
【问题描述】:

我正在努力解决“孤岛和差距”问题。这适用于 SQL Server 2008 / 2012(我们在两者上都有数据库)。

我有一张表格,用于跟踪 Pass Outlet 的“可用”序列号;即巴士通行证、门票、迪士尼乐园门票等。这些序列号是VARCHAR,可以是数字和字符的任意组合……任意长度,直到定义列的最大值。 . 这是VARCHAR(30)。这就是我在 VIEW 的语法/设计上苦苦挣扎的地方。

包含所有这些数据的表 (IM_SER) 的主键包括:

ITEM_NO...VARCHAR(20),  
SERIAL_NO...VARCHAR(30)

在许多情况下……尤其是涉及不同类型的“公共汽车通行证”时,那些 Serial-# 很容易追踪到数以万计。所需要的......是 SQL Server 中的一个简单视图......它只是输出可用序列号的连续范围......直到找到 GAP(即序列中的中断)。例如,假设对于给定的 Item-#,我们手头有以下 Serial-#:

123  
124  
125  
139  
140  
ABC123  
ABC124  
ABC126   
XYZ240003  
XYY240004

在我上面的示例中,输出将显示如下:

123  -to-  125  
139  -to-  140  
ABC123  -to-  ABC124  
ABC126  -to-  ABC126  
XYZ240003  to  XYZ240004

总共会有 10 个 Serial-#...但由于我们输出的是顺序范围...只需要 5 行输出。这有意义吗?请让我知道......再一次,谢谢你!......马克

【问题讨论】:

  • 序列号的不同格式将是一个问题。在您的示例中,您希望如何处理 ABC1244?
  • 你能把你的号码分成两部分,字符串部分(空,ABC 或 XYZ)+然后是数字吗?这样您就可以分别处理字段并为数字进行所需的间隙和孤岛计算。
  • 嗨 TheMadDBA。如果我们有一个记录,给定上面的例子,带有“ABCD1244”,那么我们必须有六行输出,因为你是对的,因为它不会落入顺序范围。嗨詹姆斯Z。我不知道如何做到这一点。这就是为什么我需要语法帮助 :-) 谢谢!...马克
  • 好吧,如果没有语法,您能否定义和描述如何可靠地拆分字符串的逻辑,以便您可以严格按数字部分排序?在您的帖子中,您说它们可以是数字和字符的任意组合。 “A1A”和“A1B”会发生什么?
  • 嗨 Tab Allerman...我明白你的意思。好的...所以微调我的逻辑...这些序列号将采用“######”(仅限数字)、“XXXXX”(仅限字母)、“# ##XXX”(数字后字母)或“XXX###”(字母后数字)。我们不会有 Alpha-Numeric-Alpha 的情况,我不好,抱歉。

标签: sql-server sql-server-2008


【解决方案1】:

这应该让你开始......有趣的部分将是确定是否存在差距。您将不得不稍微不同地处理每种串行格式以确定是否存在间隙...

select x.item_no,x.s_format,x.s_length,x.serial_no,
LAG(x.serial_no) OVER (PARTITION BY x.item_no,x.s_format,x.s_length 
 ORDER BY x.item_no,x.s_format,x.s_length,x.serial_no) PreviousValue,
LEAD(x.serial_no) OVER (PARTITION BY x.item_no,x.s_format,x.s_length 
 ORDER BY x.item_no,x.s_format,x.s_length,x.serial_no) NextValue
from 
(
 select item_no,serial_no,
 len(serial_no) as S_LENGTH,
 case
 WHEN PATINDEX('%[0-9]%',serial_no) > 0 AND
      PATINDEX('%[a-z]%',serial_no) = 0 THEN 'NUMERIC'
 WHEN PATINDEX('%[0-9]%',serial_no) > 0 AND
      PATINDEX('%[a-z]%',serial_no) > 0 THEN 'ALPHANUMERIC'
 ELSE 'ALPHA'     
 end as S_FORMAT
 from table1 ) x
 order by item_no,s_format,s_length,serial_no

http://sqlfiddle.com/#!3/5636e2/7

| item_no |     s_format | s_length | serial_no | PreviousValue | NextValue |
|---------|--------------|----------|-----------|---------------|-----------|
|       1 |        ALPHA |        4 |      ABCD |        (null) |      ABCF |
|       1 |        ALPHA |        4 |      ABCF |          ABCD |    (null) |
|       1 | ALPHANUMERIC |        6 |    ABC123 |        (null) |    ABC124 |
|       1 | ALPHANUMERIC |        6 |    ABC124 |        ABC123 |    ABC126 |
|       1 | ALPHANUMERIC |        6 |    ABC126 |        ABC124 |    (null) |
|       1 | ALPHANUMERIC |        9 | XYY240004 |        (null) | XYZ240003 |
|       1 | ALPHANUMERIC |        9 | XYZ240003 |     XYY240004 |    (null) |
|       1 |      NUMERIC |        3 |       123 |        (null) |       124 |
|       1 |      NUMERIC |        3 |       124 |           123 |       125 |
|       1 |      NUMERIC |        3 |       125 |           124 |       139 |
|       1 |      NUMERIC |        3 |       139 |           125 |       140 |
|       1 |      NUMERIC |        3 |       140 |           139 |    (null) |

【讨论】:

  • 嗨 TheMadDBA。好的,所以我查看了您的代码,并对其进行了轻微更改,以使 Serial-# 都“按顺序”排列,如下所示: order by item_no,s_format,s_length,serial_no 现在,使用您的 SQLFiddle,它们都是“按顺序”可以这么说,这很好。我不明白的是,在“范围”中输出这个的语法是什么?是否可以在这里进行某种类型的分组,或者我错过了这条船?请让我知道...我很困惑...谢谢!...马克
  • 好吧,我没有时间为您编写所有内容,但是...您必须添加逻辑以确定序列号是否按顺序排列并输出另一列(使用前面的和下一个要比较的值列)。然后,您可以根据需要将另一个选择包裹起来以进行过滤和/或分组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多