TSQL 获取范围或逗号分隔的数字

TSQL Get Numbers as Range or Comma delimited

我正在尝试组合包装数量,按订单号分组。 目前我将它与 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

有人知道这怎么可能吗?

最后我想要这样的东西:

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

从这样的角度来看:

感谢您的帮助

你问的太多了,我们先关注这个需求:

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,'');

Returns:

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