Hoje apresentarei o tipo de dados geométrico (geometry) para que nessa aula você aprenda a fazer seu primeiro gráfico no SQL Server. Também veremos como a área de objetos, como calcular a distância entre objetos, bem como fazer desenhos diversos usando polígonos, pontos, retas, círculos e outras formas geométricas.

 

Formas geométricas no SQL Server

Antes de pensarmos em desenhos completos e gráficos, precisamos aprender a representar as principais formas geométricas no SQL Server. Veja como é simples fazer isso usando os exemplos abaixo:

 

select geometry::Parse('linestring(0 0, 2 2)') as reta

 

select geometry::Parse('linestring(0 0, 2 2, 4 0, 0 0)') as triangulo

select geometry::Parse('multilinestring((0 0, 2 2), (0 2, 2 0), (1 2, 1 0), (0 1, 2 1))') as asterisco

select geometry::Parse('circularstring(0 1, 1 0, 2 1)') as semicirculo

select geometry::Parse('circularstring(0 1, 1 0, 2 1, 1 2, 0 1)') as circulo

select geometry::Parse('circularstring(0 1, 1 0, 2 1, 1 2, 1 1)') as semicirculo2

select geometry::Parse('polygon((1 1, 5 1, 4 3, 2 3, 1 1))') as trapezio

select geometry::Parse('multipolygon(((1 1, 5 1, 4 3, 2 3, 1 1), (6 1, 8 1, 8 3, 6 3, 6 1)))') as multipoligonos

select geometry::Parse('curvepolygon(circularstring(0 1, 1 0, 2 1, 1 2, 0 1))') as circulo

select geometry::Parse('curvepolygon(circularstring(0 4, 4 0, 8 4, 4 8, 0 4), circularstring(2 4, 4 2, 6 4, 4 6, 2 4))') as circulos

select geometry::Parse('compoundcurve(circularstring (0 0, 1 2.1082, 3 6.3246, 0 7, -3 6.3246, -1 2.1082, 0 0))') as pizza

select geometry::Parse('curvepolygon(compoundcurve(circularstring(0 0, 1 2.1082, 3 6.3246, 0 7, -3 6.3246, -1 2.1082, 0 0)))') as pizza

Desenhando no SQL Server

Agora que você já sabe representar as formas básicas, hora de fazer seu primeiro desenho!

 

[sociallocker id=”5114″]

select geometry::Parse('
	geometrycollection(
		circularstring(0 1, 1 0, 2 1, 1 2, 0 1),
		circularstring(0.4 1.2, 0.75 1.1, 0.8 1.2, 0.8 1.3, 0.4 1.2),
		circularstring(1.2 1.2, 1.55 1.1, 1.6 1.2, 1.6 1.3, 1.2 1.2),
		circularstring(0.4 0.7, 1 0.3, 1.6 0.7),
		linestring(1 0, 1 -4),
		linestring(1 -4, -0.5 -7),
		linestring(1 -4, 2.5 -7),
		linestring(1 -1.5, -1 -2),
		linestring(1 -1.5, 3 -2)
	)') -- cabeça, olho_e, olho_d, boca, corpo, perna_e, perna_d, braco_e, braco_d

[/sociallocker]

Seu primeiro gráfico no SQL Server

Vamos agora para o business! Sabendo como funciona a montagem de gráficos do SQL, fica fácil manipularmos as coordenadas XY para que a forma geométrica resultante seja um gráfico. Veja o exemplo abaixo:

[sociallocker id=”5114″]

if object_id('tempdb..#vendas') is not null drop table #vendas
create table #vendas (ano int not null primary key, vl_vendido numeric(10, 2) not null)
insert into #vendas values
	(2012, 13),
	(2013, 17),
	(2014, 15),
	(2015, 17),
	(2016, 19),
	(2017, 19),
	(2018, 20),
	(2019, 17),
	(2020, 19)
select * from #vendas

declare @dados as varchar(8000);
set @dados = stuff ((
		select ',' + convert(varchar, ano) + ' ' + convert(varchar, vl_vendido)
		from #vendas order by ano for xml path('')
	), 1, 1, '');
print @dados

select
	geometry::Parse('linestring(' + @dados + ')') as desenho,
	geometry::Parse('linestring(' + @dados + ')').ToString() as dado_geometrico_em_texto

[/sociallocker]

Cálculos geométricos no SQL Server

Claro que não poderíamos falar de geometria sem os cálculos que você adorava fazer no segundo grau… certo?
Bom, seja você fã ou não da matemática e trigonometria, tenho uma ótima notícia! Os cálculos geométricos no SQL são uma verdadeira barbada! Literalmente com uma linha de comando você calcula a área de objetos, veja os exemplos abaixo:

-- STArea: Cálculo de área
-- Área trapézio = ((base de cima + base de baixo) * altura) / 2) ==> ((3 + 5) * 3) / 2 ==> 12m
declare @poligono geometry = 'polygon((0 0, 5 0, 4 3, 1 3, 0 0))'
select
	@poligono as desenho,
	@poligono.STArea() as Area_MetrosQuadrados

-- STUnion: União de polígonos
-- Área de uma estrela construida a partir de 2 triangulos
declare @t1 geometry = 'polygon((0 1, 1 1, 0.5 2, 0 1))'
declare @t2 geometry = 'polygon((0 1.64, 1 1.64, 0.5 0.64, 0 1.64))'
select
	@t1.STUnion(@t2) as imagem,
	@t1.STUnion(@t2).STArea() as Area

-- UnionAggregate: União de polígonos de uma tabela
declare @poligonos table (obj geometry)
insert into @poligonos values
	(geometry::Parse('polygon((0 0, 0 2, 2 2, 2 0, 0 0))')),
	(geometry::Parse('polygon((1 1, 3 1, 3 3, 1 3, 1 1))')),
	(geometry::Parse('polygon((3 3, 5 3, 5 5, 3 5, 3 3))'))
select
	geometry::UnionAggregate(obj) as Imagem,
	geometry::UnionAggregate(obj).STArea() as Area_MetrosQuadrados
from @poligonos

Script completo da aula sobre geometry

Por fim, aqui vai o script completo da aula introdutória de hoje sobre geometria no SQL Server:

 

[sociallocker id=”5114″]

------------------------------------------------------------------
-- GEOMETRY: Formas geométricas no SQL Server (SQL2008+)
------------------------------------------------------------------
-- Ponto: Cada par de números representa uma coordenada (x, y). Exemplo abaixo: x=10, y=20
select geometry::Parse('point (10 20)') as ponto
select geometry::Parse('multipoint ((10 20), (10 21))') as pontos

-- Linha reta: pode ser usada para criar figuras, porém representa somente as bordas, ou seja, não tem área interna
select geometry::Parse('linestring(0 0, 2 2)') as reta
select geometry::Parse('linestring(0 0, 2 2, 4 0, 0 0)') as triangulo
select geometry::Parse('multilinestring((0 0, 2 2), (0 2, 2 0), (1 2, 1 0), (0 1, 2 1))') as asterisco

-- Linha curva:
select geometry::Parse('circularstring(0 1, 1 0, 2 1)') as semicirculo
select geometry::Parse('circularstring(0 1, 1 0, 2 1, 1 2, 0 1)') as circulo
select geometry::Parse('circularstring(0 1, 1 0, 2 1, 1 2, 1 1)') as semicirculo2

-- Polígonos retos: figura geométrica com área interna. (O primeiro e último ponto precisam ser ligados!)
select geometry::Parse('polygon((1 1, 5 1, 4 3, 2 3, 1 1))') as trapezio
select geometry::Parse('multipolygon(((1 1, 5 1, 4 3, 2 3, 1 1), (6 1, 8 1, 8 3, 6 3, 6 1)))') as multipoligonos

-- Polígonos curvos:
select geometry::Parse('curvepolygon(circularstring(0 1, 1 0, 2 1, 1 2, 0 1))') as circulo
select geometry::Parse('curvepolygon(circularstring(0 4, 4 0, 8 4, 4 8, 0 4), circularstring(2 4, 4 2, 6 4, 4 6, 2 4))') as circulos

-- Curva composta: desenho flexivel
select geometry::Parse('compoundcurve(circularstring (0 0, 1 2.1082, 3 6.3246, 0 7, -3 6.3246, -1 2.1082, 0 0))') as pizza
select geometry::Parse('curvepolygon(compoundcurve(circularstring(0 0, 1 2.1082, 3 6.3246, 0 7, -3 6.3246, -1 2.1082, 0 0)))') as pizza

---------------------------------------------------
-- Seu primeiro DESENHO no SQL!
---------------------------------------------------
select geometry::Parse('
	geometrycollection(
		circularstring(0 1, 1 0, 2 1, 1 2, 0 1),
		circularstring(0.4 1.2, 0.75 1.1, 0.8 1.2, 0.8 1.3, 0.4 1.2),
		circularstring(1.2 1.2, 1.55 1.1, 1.6 1.2, 1.6 1.3, 1.2 1.2),
		circularstring(0.4 0.7, 1 0.3, 1.6 0.7),
		linestring(1 0, 1 -4),
		linestring(1 -4, -0.5 -7),
		linestring(1 -4, 2.5 -7),
		linestring(1 -1.5, -1 -2),
		linestring(1 -1.5, 3 -2)
	)') -- cabeça, olho_e, olho_d, boca, corpo, perna_e, perna_d, braco_e, braco_d

---------------------------------------------------
-- Seu primeiro GRÁFICO no SQL!
---------------------------------------------------
if object_id('tempdb..#vendas') is not null drop table #vendas
create table #vendas (ano int not null primary key, vl_vendido numeric(10, 2) not null)
insert into #vendas values
	(2012, 13),
	(2013, 17),
	(2014, 15),
	(2015, 17),
	(2016, 19),
	(2017, 19),
	(2018, 20),
	(2019, 17),
	(2020, 19)
select * from #vendas

declare @dados as varchar(8000);
set @dados = stuff ((
		select ',' + convert(varchar, ano) + ' ' + convert(varchar, vl_vendido)
		from #vendas order by ano for xml path('')
	), 1, 1, '');
print @dados

select
	geometry::Parse('linestring(' + @dados + ')') as desenho,
	geometry::Parse('linestring(' + @dados + ')').ToString() as dado_geometrico_em_texto

---------------------------------------------------
-- Cálculos de geometria
---------------------------------------------------
-- STArea: Cálculo de área
-- Área trapézio = ((base de cima + base de baixo) * altura) / 2) ==> ((3 + 5) * 3) / 2 ==> 12m
declare @poligono geometry = 'polygon((0 0, 5 0, 4 3, 1 3, 0 0))'
select
	@poligono as desenho,
	@poligono.STArea() as Area_MetrosQuadrados

-- STUnion: União de polígonos
-- Área de uma estrela construida a partir de 2 triangulos
declare @t1 geometry = 'polygon((0 1, 1 1, 0.5 2, 0 1))'
declare @t2 geometry = 'polygon((0 1.64, 1 1.64, 0.5 0.64, 0 1.64))'
select
	@t1.STUnion(@t2) as imagem,
	@t1.STUnion(@t2).STArea() as Area

-- UnionAggregate: União de polígonos de uma tabela
declare @poligonos table (obj geometry)
insert into @poligonos values
	(geometry::Parse('polygon((0 0, 0 2, 2 2, 2 0, 0 0))')),
	(geometry::Parse('polygon((1 1, 3 1, 3 3, 1 3, 1 1))')),
	(geometry::Parse('polygon((3 3, 5 3, 5 5, 3 5, 3 3))'))
select
	geometry::UnionAggregate(obj) as Imagem,
	geometry::UnionAggregate(obj).STArea() as Area_MetrosQuadrados
from @poligonos
go

-- STIntersection: Intersection de polígonos
-- Pentagono a partir de 2 triangulos
declare @t1 geometry = 'polygon((0 1, 1 1, 0.5 2, 0 1))'
declare @t2 geometry = 'polygon((0 1.64, 1 1.64, 0.5 0.64, 0 1.64))'
select
	@t1.STIntersection(@t2) as imagem,
	@t1.STIntersection(@t2).STArea() as Area

-- Distância: STDistance
declare @poligono1 geometry = 'curvepolygon(circularstring(0 1, 1 0, 2 1, 1 2, 0 1))'
declare @poligono2 geometry = 'polygon((5 0, 7 0, 7 2, 5 2, 5 0))'
select
	geometry::Parse('geometrycollection(' + @poligono1.ToString() + ', ' + @poligono2.ToString() + ')'),
	@poligono1.STDistance(@poligono2) as distancia

[/sociallocker]

CONCLUSÃO

Apesar da implementação de geometria do SQL ser bastante simples e ter inúmeras possíveis utilizações, hoje poucas pessoas conhecem essa tecnologia, e menos pessoas ainda a utilizam comercialmente.

Está ai mais um recurso que pode ajudar a nos destacarmos no mercado, e tudo começa com o seu primeiro gráfico no SQL Server!

Espero que também tenha gostado desse conteúdo.

 

Abraço do seu amigo Josué 🙂

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *