【问题标题】:TSQL Get Numbers as Range or Comma delimitedTSQL 获取范围或逗号分隔的数字
【发布时间】:2018-08-15 14:41:56
【问题描述】:

我正在尝试合并包装数量,按订单号分组。 目前我将它与 STUFF 结合为逗号分隔字符串。 所以我现在举个例子:1-001, 1-002, 1-003

但是如果数字是 1-001, 1-002, 1-003, 1-004, 1-007 我想得到这个 Packagenumbers 的范围是有序的并且这个范围(或单个包装)用逗号分隔。

示例:

Packagings: 1-001, 1-002, 1-003, 1-004, 1-007, 1-008, 2-001
Expected: 1-001 to 1-004, 1-007 to 1-008, 2-001

我目前的方法是这样的:

SELECT
    o.OrderNumber 
    , op.PositionNumber
    , STUFF((
        SELECT ',' + ifp.Packnumber
        FROM FilledPackage ifp
        INNER JOIN PositionInFIlledPackage pifp
        ON ifp.FilledPackageId = pifp.FilledPackageId
        WHERE 
            ifp.OrderNumber = o.OrderNumber
            AND pifp.PositionNumber = op.PositionNumber
        ORDER BY ifp.Code, ifp.PackOfTypeCounter
        FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
      ,1,1,'') AS Packagings
FROM MyOrder o
INNER JOIN MyPosition op
ON o.OrderId = op.OrderId
GROUP BY 
    o.OrderNumber 
    , op.PositionNumber
  • ifp.Code 是包装类型(如 1-00x 中的 1)
  • ifp.PackOfTypeCounter 是某个类型的当前 Packagenumber(如 x-001 中的 1)
  • PackNumber 是一个类似于 1-002 的字符串(1 => 包类型,2 => 包号) 示例:PackNumber = ifp.Code + "-" + ifp.PackOfTypeCounter

有人知道这怎么可能?

最后我想要这样的东西:

Position 1: Pack: 4-001 to 4-008
Position 2: Pack: 1-001 to 1-004, 2-001 to 2-002, 4-009
Position 3: Pack: 4-010
Position 3: Pack: 1-005 to 1-007, 4-011

从这样的角度来看:

  • 订单号
  • 职位编号
  • PackagingCode (int) => PackageType => 1
  • PackOfTypeCounter (int) => 001
  • FullPackageNumber (1-001)

感谢您的帮助

【问题讨论】:

  • 您是否还可以包含示例数据以与您提供的示例输出一起使用。
  • 您使用的是什么版本的 SQL Server?
  • @Alan MS SQL 2016

标签: sql-server tsql range delimited


【解决方案1】:

你问的很多,让我们首先关注这个要求:

Packagings: 1-001, 1-002, 1-003, 1-004, 1-007, 1-008, 2-001
Expected: 1-001 to 1-004, 1-007 to 1-008, 2-001

有了DelimitedSplit8K,以及一些关于解决差距和孤岛的基本知识,这有点容易:

DECLARE @packagings VARCHAR(1000) = '1-001, 1-002, 1-003, 1-004, 1-007, 1-008, 2-001';

SELECT STUFF(
(
  SELECT 
    ', '+
    CASE 
      WHEN MIN(g.txt) = MAX(g.txt) 
      THEN CAST(g.txtGroup AS VARCHAR(100))+'-'+CAST(MIN(g.txt) AS VARCHAR(100)) 
      ELSE CAST(g.txtGroup AS VARCHAR(100))+'-'+CAST(MIN(g.txt) AS VARCHAR(100))+' to '+
           CAST(g.txtGroup AS VARCHAR(100))+'-'+CAST(MAX(g.txt) AS VARCHAR(100))
    END
  FROM
  (
    SELECT txtGroup = t1.txt, t2.txt, grouper = t2.txt - split.ItemNumber
    FROM dbo.DelimitedSplit8K(REPLACE(@packagings,' ',''),',') AS split
    CROSS APPLY (VALUES(CHARINDEX('-', split.item)))           AS mid(pos)
    CROSS APPLY (VALUES(SUBSTRING(split.item,1,mid.pos-1)))    AS t1(txt)
    CROSS APPLY (VALUES(SUBSTRING(split.item,mid.pos+1,8000))) AS t2(txt)
  ) g
  GROUP BY g.txtGroup, g.grouper
  ORDER BY g.txtGroup
  FOR XML PATH('')
),1,2,'');

返回:

1-001 to 1-004, 1-007 to 1-008, 2-001

【讨论】:

  • 我自己试过这个,效果很好。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-05
  • 2014-07-20
  • 1970-01-01
  • 2014-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多