Re: select count of all overlapping geometries and return 0 if none.

From: Steve Midgley <science(at)misuse(dot)org>
To: pgsql-sql(at)postgresql(dot)org
Cc: dufferdo25(at)yahoo(dot)com
Subject: Re: select count of all overlapping geometries and return 0 if none.
Date: 2009-03-13 17:32:36
Message-ID: 20090313173255.C251F63246F@mail.postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-sql

At 06:20 AM 3/13/2009, pgsql-sql-owner(at)postgresql(dot)org wrote:
>Message-ID: <457532(dot)70947(dot)qm(at)web45913(dot)mail(dot)sp1(dot)yahoo(dot)com>
>Date: Thu, 12 Mar 2009 10:28:19 -0700 (PDT)
>From: Duffer Do <dufferdo25(at)yahoo(dot)com>
>Subject: select count of all overlapping geometries and return 0 if
>none.
>To: pgsql-sql(at)postgresql(dot)org
>X-Archive-Number: 200903/24
>X-Sequence-Number: 32267
>
>Hello all,
>I have 2 tables locations and user_tracker:
>
>locations has 2 columns
>location_name
>location_geometry
>
>user_tracker has 3 columns
>user_name
>user_geometry
>user_timestamp
>
>
>locations table is coordinates and names of areas of interest.
>user_tracker basically is an archive of a user's movements as he pans
>his map.
>
>I have a need to assign a ranking of locations based on how many times
>users have intersected this location.
>
>The problem I am having is that my query only returns locations that
>have been intersected by a user.
>I need it to return ALL locations and a zero if this location has not
>been intersected.
>
>As an example:
>
>LOCATIONS
>1: Talahassee, FL | talahassee's bounding box
>2: Manhattan, NY | Manhattan's bounding box
>3: Frankfurt, GE | Frankfurt's bounding box
>
>
>USER_TRACKER
>john doe | geometry that overlaps Frankfurt | today
>john doe | geometry that overlaps Frankfurt | today
>john doe | geometry that overlaps Frankfurt | today
>john doe | geometry that overlaps Frankfurt | yesterday
>john doe | geometry that overlaps Frankfurt | Monday
>john doe | geometry that overlaps Frankfurt | Sunday
>Mary Jane | geometry that overlaps Manhattan | today
>Rob Roy | geometry that overlaps Manhattan | today
>Rob Roy | geometry that overlaps Manhattan | today
>
>
>I want to return the following:
>locations | number_visits
>Frankfurt | 6
>Manhattan | 3
>Talahassee | 0
>
>My query only returns:
>Frankfurt | 6
>Manhattan | 3
>
>Now I have really simplified this example for readability, my actual
>tables are more complex.
>
>How can I accomplish this?
>
>My query:
>SELECT count(user_name) as number_visits, location_name from
>locations, user_tracker WHERE user_geometry && location_geometry
>
>Thanks in advance

Hi,

I am stuck at an airport right now, and had the time to hack out your
solution. I hope it helps. In the future, it would be helpful to the
list (and more likely to yield responses) if you include the
create/insert statements such as what I've put together below. It makes
it much easier for people to quickly get you an answer - in this case I
had a spare 20 minutes so I did it for you.

Also, I put a gist index on your locations table but that assumes your
areas are flat, which isn't right for spherical coordinates on the
earth. PostGis should be able to get you closer, if that kind of
accuracy matters.

Anyway, here are the table setups and what I believe is the solution
query:

-- START SQL SCRIPT --

drop table if exists locations;
create table locations
(id serial,
name varchar(255),
area circle);

insert into locations (name, area)
values
('Talahassee, FL','((0,0),1)'),
('Manhattan, NY','((2,0),1)'),
('Frankfurt, GE','((4,0),1)');

CREATE INDEX idx_locations_area ON locations USING gist ("area");

drop table if exists user_tracker;
create table user_tracker
(id serial primary key,
name varchar(255),
location point,
time varchar(255));

insert into user_tracker (name,location,time)
values
('john doe', '(4,0)', 'today'),
('john doe', '(4,0)', 'today'),
('john doe', '(4,0)', 'today'),
('john doe', '(4,0)', 'yesterday'),
('john doe', '(4,0)', 'Monday'),
('john doe', '(4,0)', 'Sunday'),
('Mary Jane', '(2,0)', 'today'),
('Rob Roy', '(2,0)', 'today'),
('Rob Roy', '(2,0)', 'today');

-- SOLUTION QUERY HERE --
select count(user_tracker.id), locations.name from user_tracker
right outer join locations on user_tracker.location <@ locations.area
group by locations.name;

-- END SQL SCRIPT --

OUTPUT:

>3;"Manhattan, NY"
>0;"Talahassee, FL"
>6;"Frankfurt, GE"

Steve

Browse pgsql-sql by date

  From Date Subject
Next Message Mina R Waheeb 2009-03-13 18:38:06 Re: Permanent alias for postgresql table
Previous Message seb JACK 2009-03-13 12:49:28 RE : [SQL] Convert text from UTF8 to ASCII