tony_lu 1 Denunciar post Postado Setembro 21, 2011 Ola pessoal, tudo bem? Preciso de uma ajuda, preciso marcar em um app do google maps, os usuarios mais proximos de um determinado endereço... No banco ja consigo gravar a latitude e longitude de todos os usuarios no ato do cadastro, agora preciso saber como selecionar os usuarios sabendo quais os mais proximos de um determinado endereço... ja vi sites que marcam até quantos km um usuario ou empresa esta de um determinado ponto... alguem pode me ajudar? A codificação do app que estou utilizando é esta: var mrk = []; mrk.push(new mrkitem('Vit', 'botoi', 'usuario', '20100811123843_boi.jpg', -23.9789580, -46.3121512)); mrk.push(new mrkitem('Rafa', 'rafaelbr', 'usuario', '20100813170104_rafaelbr.jpg', -23.9772151, -46.3082780)); mrk.push(new mrkitem('João', 'c0d3r00t', 'usuario', '20100719235819_c0d3r00t.jpg', -23.9581367, -46.3925527)); mrk.push(new mrkitem('Rodrigo', 'digo.dark', 'usuario', '20100613004027_gen_avatar.gif', -23.9366827, -46.3882702)); mrk.push(new mrkitem('Celso', 'alsa', 'usuario', '20100613004027_geic_avatar.gif', -23.9739162, -46.3122721)); mrk.push(new mrkitem('allex', 'alexalves', 'usuario', '201009131128_alex.jpg', -23.9614568, -46.3247244)); Obrigado pessoal! Compartilhar este post Link para o post Compartilhar em outros sites
hinom 5 Denunciar post Postado Setembro 21, 2011 Faça no próprio MySQL Não esqueça de que precisa converter os graus para radianos: radiano = graus * PI / 180 exemplo prático: $distance = 15; // km. Busca os registros com coordenadas num raio de 15 kilômetros // coordenada atual do usuário $longitude = '-23.9789580'; $latitude = '-46.3121512'; $qry = " SELECT"; $qry .= " (((acos(sin((".$latitude."*pi()/180)) * sin((`latitude`*pi()/180))+cos((".$latitude."*pi()/180)) * cos((`latitude`*pi()/180)) * cos(((".$longitude."- `longitude`)*pi()/180))))*180/pi())*60*1.1515*1.609344) as distance "; $qry .= " FROM `MyTable`"; $qry .= " WHERE distance <= ".$distance; echo $qry; * Considerando que os nomes dos campos na tabela para latitude e longitude, sejam respectivamente "latitude" e "longitude". Portanto, modifique de acordo com as nomenclaturas das sua tabela. Caso queira pesquisar mais sobre o assunto, pesquise por "haversine mysql" ou "haversi mysql".. Note que o exemplo acima faz o cálculo em kilômetros. Compartilhar este post Link para o post Compartilhar em outros sites
tony_lu 1 Denunciar post Postado Setembro 21, 2011 Muito obrigado pela ajuda hinon! abs! Compartilhar este post Link para o post Compartilhar em outros sites
tony_lu 1 Denunciar post Postado Setembro 22, 2011 Muito obrigado pela ajuda hinon! abs! Ola.... fiz o teste agora e ocorreu um erro: Unknown column 'distance' in 'where clause' Sabe como eu posso resolver? Segue abaixo a linha do sql que utilizei...os campos sao lat e long: SELECT (((acos(sin((-46.3121512*pi()/180)) * sin((`lat`*pi()/180))+cos((-46.3121512*pi()/180)) * cos((`lat`*pi()/180)) * cos(((-23.9789580- `long`)*pi()/180))))*180/pi())*60*1.1515*1.609344) AS distance FROM `usuario` WHERE distance <= 15 Obrigado Compartilhar este post Link para o post Compartilhar em outros sites
hinom 5 Denunciar post Postado Setembro 22, 2011 Desculpe, no lugar de WHERE utilize HAVING, porque o MySQL não reconhece alias na cláusula WHERE, mas reconhece se usar HAVING $qry .= " WHERE distance <= ".$distance; troque por $qry .= " HAVING distance <= ".$distance; Outra solução seria repetir a condicional do alias mas não é conveniente repetir a mesma instrução devido ao seu tamanho. Veja também: http://dev.mysql.com/doc/refman/5.5/en/problems-with-alias.html Compartilhar este post Link para o post Compartilhar em outros sites
tony_lu 1 Denunciar post Postado Setembro 22, 2011 Obrigado pela ajuda, agora nao esta dando mais nenhum erro, mas esta retornando vazio... mas o banco tem diversos usuarios com os campos de lat e long... mas nao retorna nada...o que pode ser? Segue: SELECT (((acos(sin((-46.3121512*pi()/180)) * sin((`lat`*pi()/180))+cos((-46.3121512*pi()/180)) * cos((`lat`*pi()/180)) * cos(((-23.9789580- `long`)*pi()/180))))*180/pi())*60*1.1515*1.609344) AS distance FROM `usuario` HAVING distance <= 15 Agradeço se puder me ajudar novamente... Compartilhar este post Link para o post Compartilhar em outros sites
hinom 5 Denunciar post Postado Setembro 22, 2011 Há outros detalhes importantes, por exemplo, o datatype da coluna no MySQL Precisa definir no mínimo como FLOAT(9,6) Ou seja, um número flutuante (decimal) com capacidade para 9 dígitos, porém, com suporte para 6 casas decimais. A desvantagem é que não poderá obter outros recursos a partir do número original da coordenada, pois gravará somente 9 dígitos, sendo que uma coordenada pode conter 13 casas decimais. A vantagem é que para servidores em produção, a performance é muito melhor do que usar o "GIS Spatial", que permite guardar os dados em formatos geométricos: http://dev.mysql.com/doc/refman/5.0/en/populating-spatial-columns.html Mas esse assunto sobre o a extensão GIS Spatial é outra conversa, pois a recomendação de uso depende de cada caso. Por hora, verifique se os seus campos "lat" e "long" estão definidos como FOAT(9,6) e execute a query novamente Apenas para confirmar, fiz um teste rápido, usando coordenadas dentro do raio de 15km USE test; SELECT (((acos(sin((136.875195*pi()/180)) * sin((`latitude`*pi()/180))+cos((136.875195*pi()/180)) * cos((`latitude`*pi()/180)) * cos(((35.172259- `longitude`)*pi()/180))))*180/pi())*60*1.1515*1.609344) as distance FROM `coords` HAVING distance <= 15 DDL da tabela USE test; CREATE TABLE `coords` ( `id` int(3) NOT NULL AUTO_INCREMENT, `longitude` float(9,6) NOT NULL, `latitude` float(9,6) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; Dummy data, para testes USE test; INSERT INTO `coords` VALUES ('1', '35.173237', '136.883179'), ('2', '35.181072', '136.885834'), ('3', '35.172737', '136.892273'), ('4', '35.165745', '136.890549'); obs: "USE test;" é para referenciar uma base de dados. Troque para o nome da sua base de dados caso esteja conectado a múltiplas bases de dados. Compartilhar este post Link para o post Compartilhar em outros sites