Archive for the ‘Banco de Dados’ Category

[PostgreSQL] Obter locais próximos (fórmula de Haversine)

terça-feira, agosto 16th, 2011

Sabe aquele recurso que algumas redes sociais têm, de exibir os pontos próximos à sua localização? Sim, é possível e bem simples de fazer. A fórmula matemática que faz tudo funcionar chama-se Fórmula de Haversine. Sem mais delongas, vamos ao código:

-- Cálculo da distância entre dois pontos usando a fórmula de Haversine em PostgreSQL
CREATE OR REPLACE FUNCTION distancia_km(lat1 NUMERIC, lng1 NUMERIC, lat2 NUMERIC, lng2 NUMERIC)
RETURNS DOUBLE PRECISION AS
$BODY$
	SELECT 6371 * acos(
		sin( radians($1) ) * sin( radians( $3 ))
	      + cos( radians($1) ) * cos( radians( $3 )) * cos(radians($4) - radians($2))  )
	AS distance;
$BODY$
  LANGUAGE SQL IMMUTABLE
  COST 100;

Suponhamos que exista uma tabela de usuários onde exista os campos latitude e longitude. É fácil criar uma query usando a função acima para trazer os usuários mais próximos do seu local, em um raio de 10 Km:

SELECT * FROM usuarios WHERE distancia_km(minha_latitude, minha_longitude, latitude, longitude) < 10
AND distancia_km(minha_latitude, minha_longitude, latitude, longitude) <> 0

Serão listados os usuários que estão a menos de 10 Km de distância de você.

OBS: Se quiser usar milhas ao invés de quilômetros, use a constante 3959 ao invés de 6371 na função:

-- Cálculo da distância entre dois pontos usando a fórmula de Haversine em PostgreSQL
CREATE OR REPLACE FUNCTION distancia_milhas(lat1 NUMERIC, lng1 NUMERIC, lat2 NUMERIC, lng2 NUMERIC)
RETURNS DOUBLE PRECISION AS
$BODY$
	SELECT 3959 * acos(
		sin( radians($1) ) * sin( radians( $3 ))
	      + cos( radians($1) ) * cos( radians( $3 )) * cos(radians($4) - radians($2))  )
	AS distance;
$BODY$
  LANGUAGE SQL IMMUTABLE
  COST 100;

[PostgreSQL] Paginação fácil fácil no PostgreSQL

sexta-feira, outubro 2nd, 2009

Trabalhar com paginação de dados no PostgreSQL é muito fácil. As cláusulas usadas para paginação são LIMIT e OFFSET. A fórmula básica seria o seguinte:

SELECT * FROM tabela
    LIMIT <número de itens por página>
    OFFSET(<página> - 1) * <número de itens por página>

Muito fácil! :)

[PostgreSQL] Usando ORDER BY em cláusulas UNION

terça-feira, setembro 15th, 2009

Uma dica rápida, mas que pode poupar um bom tempinho. Usar ORDER BY em queries que usam a cláusula UNION é bem mais simples do que parece. Suponhamos que temos duas tabelas, tb_cidades e tb_paises, e queremos trazer em uma única query o id e o nome tanto de tb_cidades quanto de tb_paises. Para isso combinamos duas queries SELECT usando a cláusula UNION:

SELECT c.cidade_id, c.nome FROM tb_cidades c
UNION
SELECT p.pais_id, p.nome FROM tb_paises p

Teremos assim, em uma única query, tanto cidades quanto países. Mas, e a ordenação?? É aí que muita gente se atrapalha, mas a solução é bem simples:

1) Atribua um alias em comum para as colunas que serão ordenadas. Se for a coluna de ID, coloque o mesmo alias tanto para cidades quanto para países.

2) Utilize este alias no ORDER BY.

Então vamos alterar a query acima para ordenar pela coluna nome de tb_cidades e tb_paises:

SELECT c.cidade_id, c.nome AS coluna_nome FROM tb_cidades c
UNION
SELECT p.pais_id, p.nome AS coluna_nome FROM tb_paises p
ORDER BY coluna_nome

Simples assim. Wink

Distribuindo tabelas MySQL em vários servidores

quinta-feira, junho 5th, 2008

Essa dica eu encontrei no blog do Cristiano Anderson.

Os frameworks para desenvolvimento web como o Django possuem um ótimo ORM, facilitando muito a criação de aplicações rápidas e eficientes. Da mesma forma que facilita o desenvolvimento, atrapalha em alguns pontos, como por exemplo se o desenvolvedor desejar utilizar mais de um banco de dados para a mesma aplicação. Embora seja possível fazer, as alterações no settings e no código fogem um pouco dos padrões do framework.

Existe uma forma bastante simples para dividir a carga do banco de dados entre vários servidores sem mexer em nada na aplicação. As alterações são feitas diretamente no banco de dados e ficam totalmente transparentes para o framework, é uma mão na roda para escalar melhor as aplicações. O MySQL possui um storage engine chamado Federated, que é o responsável por acessar tabelas remotas como se fossem tabelas locais do banco de dados, digamos assim, funciona como uma espécie de NFS mas para tabelas do MySQL.

Para fazer a solução funcionar, primeiro passo é verificar se os seus servidores MySQL suportam o engine Federated. Para isso, basta o comando show engines; Se encontrar a linha FEDERATED YES, é sinal que o seu banco suporta.
 Em segundo lugar, basta criar no seu banco uma tabela com o mesmo layout da tabela que deseja acessar remotamente. O layout precisa ser idêntico, senão não funciona. No final, basta definir como engine Federated e passar os parâmetros de acesso, algo como: ENGINE=FEDERATED CONNECTION=’mysql://user@192.168.1.1/banco/tabela’
Dessa forma você consegue ter acesso a uma tabela remota, como se fosse local. Essa solução é excelente para quem trabalha com frameworks que possuem o próprio ORM.
Veja mais informações detalhadas sobre o assunto nesse artigo do MySQL Brasil.

Fonte: http://christiano.blog.br/2008/06/04/distribuindo-tabelas-mysql-em-varios-servidores/

Concatenação de strings rápido e rasteiro no PostgreSQL

quinta-feira, março 27th, 2008

O PostgreSQL possui o operador de concatenação de strings || (dois pipes):

Suponhamos que nome = 'Rogério' e sobrenome 'Bragil'

SELECT (nome || ' ' || sobrenome) AS nome_completo FROM tabela

Isto retornará 'Rogério Bragil', pois houve a concatenação do campo nome ('Rogério'), do espaço e do campo sobrenome ('Bragil').