Batch driving distance - a pgRouting function

Batch driving distance - a pgRouting function

A function to batch process driving distance results for a set of input points, in this case, schools.

The function creates a table to hold the results (dropping it if it exists) and then selects each school from the your_schools table and calculates the driving distance numbers. For each school it writes the results to a temp table (temp_dd, dropping it first if it exists) and writes those results to the output table (school_driving_distance). In the end you have a table with a lot of rows (more or less depending on your cost) with which you can do neat things with QGIS Time Manager.

The schools data needs to be pre-processed to give each school an id field, school_nn, which contains the node id of the nearest network node.

Note: You'll need to VACUUM ANALYZE your output table to update the statistics.

-- Function: public.school_driving_distance()
-- DROP FUNCTION public.school_driving_distance();

CREATE OR REPLACE FUNCTION public.school_driving_distance()
  RETURNS character varying AS
$BODY$
DECLARE

  cur_school refcursor;
  v_snn integer;  --variable for the school nearest node
  v_node integer;
  v_seq integer;  --variable for the sequence id
  v_cost double precision;  --variable for the cost results
  v_geom geometry;  --variable for the output geometry
  v_sql varchar(1000);  --variable to hold some SQL
  
BEGIN
-- Drop the results table first
	RAISE NOTICE 'Dropping table...';
	v_sql:='DROP TABLE IF EXISTS public.school_driving_distance;';
	EXECUTE v_sql;
	
-- Create a new results table next
	RAISE NOTICE 'Creating table...';
	v_sql:='CREATE TABLE IF NOT EXISTS public.school_driving_distance 
	(
	  gid serial NOT NULL,
	  seq integer,
      node integer,
	  school_nn integer,
	  agg_cost double precision, 
	  geometry geometry(Point,27700), 
	  CONSTRAINT school_dd_ipk PRIMARY KEY (gid)
	);

    CREATE INDEX school_driving_distance_geometry_ixs
    ON public.school_driving_distance
    USING gist(geometry);';

	EXECUTE v_sql;
	
-- Process the schools    
	RAISE NOTICE 'Processing school...';
	OPEN cur_school FOR EXECUTE format('SELECT school_nn FROM your_schools WHERE school_nn IS NOT NULL');
	LOOP

-- Drop the temp table
	v_sql:='DROP TABLE IF EXISTS temp_dd;';
	EXECUTE v_sql;

-- Create a temp table to hold results for each school
	v_sql:='CREATE TEMPORARY TABLE temp_dd(
	  seq integer,
      node integer,
	  school_nn integer,
	  agg_cost double precision, 
	  geometry geometry(Point,27700)
	  );';
	EXECUTE v_sql;
	
	FETCH cur_school INTO v_snn;
	EXIT WHEN NOT FOUND;
	
-- Do 30 minute driving distance calculation for each school
	INSERT INTO temp_dd(seq, node, school_nn, agg_cost, geometry)
	SELECT foo.seq AS v_seq, foo.node AS v_node, v_snn AS school_nn, foo.agg_cost AS v_cost, n.the_geom AS v_geom FROM pgr_drivingDistance(
	  'SELECT ogc_fid AS id, source, target, cost, reverse_cost 
	  FROM your_network',
	  v_snn,          -- school name
	  1800) AS foo    -- change this cost to change the output
	  LEFT JOIN your_network_vertices_pgr n ON n.id = foo.node;
	  
-- Insert results into driving distance table
	EXECUTE format('INSERT INTO public.school_driving_distance(seq,node,school_nn,agg_cost,geometry) SELECT * FROM temp_dd;');
	END LOOP;
	RETURN 'Completed the driving distance calculations';
	CLOSE cur_school;
	
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
COMMENT ON FUNCTION public.school_driving_distance() IS '30 minute driving distance function for each school';

Once all the results are written to the output table you can then query the table to get the overall minimum distance to each school:

SELECT DISTINCT ON (node) *
FROM school_driving_distance
ORDER BY node, agg_cost ASC;

Here's a result from the function above processed with QGIS Time Manager and stitched together with Avidemux and VLC.

And another one.

See this stackexchange post for another way of doing it.