use tempdb;
if exists (select 1 from sys.tables where name = 'grid')
drop table grid;
if not exists (select 1 from sys.tables where name = 'tally')
begin
create table tally (i int not null);
with
a as (select 1 as [i] union select 0),
b as (select 1 as [i] from a as [a1] cross join a as [a2]),
c as (select 1 as [i] from b as [a1] cross join b as [a2]),
d as (select 1 as [i] from c as [a1] cross join c as [a2]),
e as (select 1 as [i] from d as [a1] cross join d as [a2])
insert into tally
select row_number() over (order by i) from e
create unique clustered index [CI_Tally] on tally (i)
end
create table grid (
x tinyint,
y tinyint,
cell as geometry::STGeomFromText(
'POLYGON( (' +
cast(x as varchar) + ' ' + cast(-1*y as varchar) + ', ' +
cast(x+1 as varchar) + ' ' + cast(-1*y as varchar) + ', ' +
cast(x+1 as varchar) + ' ' + cast(-1*(y+1) as varchar) + ', ' +
cast(x as varchar) + ' ' + cast(-1*(y+1) as varchar) + ', ' +
cast(x as varchar) + ' ' + cast(-1*y as varchar) +
') )'
, 0)
);
insert into grid (x, y)
values
(1,1),
(2,1),
(2,2),
(3,2),
(8,1),
(9,1),
(8,2),
(9,2),
(9,3),
(10,1);
with cte as (
select cell, row_number() over (order by x, y) as [rn]
from grid
),
cte2 as (
select cell, [rn]
from cte
where [rn] = 1
union all
select a.cell.STUnion(b.cell) as [cell], b.rn
from cte2 as a
inner join cte as b
on a.rn + 1 = b.[rn]
), cte3 as (
select cell
from cte2
where [rn] = (select count(*) from grid)
), clusters as (
select i, cell.STGeometryN(t.i) as c
from cte3 as [a]
cross join tally as [t]
where t.i <= cell.STNumGeometries()
)
select *, c.STEnvelope() from clusters
This solution solves both your original problem and this one. I like this because you can still use whatever weird coordinate system you want and it'll do what you want. All you'd have to do is modify the computed column on the grid table accordingly. I'm going to leave the computation of the corners of the envelope as an exercise to the reader. :)
By way of explanation, the computed column makes a 1x1 geometry instance out of the given x and y coordinates. From there, I essentially union all of those together which will yield a multipolygon. From there, I iterate through the individual polygons in the multipolygon to get the individual clusters. The envelope comes along for free. From here, you should be able to wrap that final select (or something very like it) in a view if you so choose.