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
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:
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 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:
------------------------------------------------------------------
-- 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
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!
Oi, aqui é o Josué. Sou o criador do site dba-pro.com.
Minha missão é ajudar pessoas a usarem o potencial do SQL Server em suas profissões, para que trabalhem felizes e bem remuneradas.
Sou consultor e empreendedor, atuando em empresas desde 2000 e dando aulas desde 2004. Adoro SQL, Excel, automatização de processos, finanças e Coaching. Quando não estou trabalhando ou estudando, gosto de leitura, games para PC, filmes, séries e conversas estimulantes.