1

I have integer values: (199903, 199908, 201203, 201408, 201410, 201501, 201503) and I would like to group these integers by integers falling within a range of 3.

In this example the grouping would be the following:

199903 (group 1)
199908 (group 2)
201203 (group 3)
201408 (group 4)
201410 (group 4)
201501 (group 5)
201503 (group 5)
Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275
decompiled
  • 1,853
  • 3
  • 14
  • 19

2 Answers2

2

You can use windowed function DENSE_RANK:

LiveDemo

CREATE TABLE #mytable(val INTEGER);

INSERT INTO #mytable(val)
VALUES(199903),(199908),(201203),(201408),(201410),(201501),(201503);

SELECT 
   val,
   [group] = DENSE_RANK() OVER (ORDER BY val/3)
FROM #mytable;

Output:

╔════════╦═══════╗
║  val   ║ group ║
╠════════╬═══════╣
║ 199903 ║     1 ║
║ 199908 ║     2 ║
║ 201203 ║     3 ║
║ 201408 ║     4 ║
║ 201410 ║     4 ║
║ 201501 ║     5 ║
║ 201503 ║     5 ║
╚════════╩═══════╝
Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275
0

I suspect you mean sequences that differ by three or less. So, a new period starts when the difference is greater than 3. In SQL Server 2012+, you can use lag() for this. In SQL Server 2008, here is one way:

with t as (
      select t.*,
             (case when t.val - tprev.val < 3 then 0 else 1 end) as IsGroupStart
      from table t outer apply
           (select top 1 t2.val
            from table t2
            where t2.val < t.val
            order by t2.val desc
           ) tprev
     ) t
select t.val, t2.grp
from t outer apply 
     (select sum(IsGroupStart) as grp
      from t t2
      where t2.val <= t.val
     ) t2;
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786