Advanced: 06 Find nearest network sites.sql

File 06 Find nearest network sites.sql, 2.2 KB (added by 231139, 11 days ago)
Line 
1CREATE OR REPLACE FUNCTION public.find_nearest_network_sites(
2 p_latitude double precision,
3 p_longitude double precision,
4 p_max_distance_m double precision DEFAULT 10000,
5 p_limit integer DEFAULT 5
6)
7RETURNS TABLE
8(
9 site_id bigint,
10 site_code text,
11 site_name text,
12 region text,
13 distance_m numeric,
14 active_technologies text
15)
16LANGUAGE plpgsql
17STABLE
18AS $$
19BEGIN
20 IF p_latitude < -90 OR p_latitude > 90 THEN
21 RAISE EXCEPTION 'Latitude must be between -90 and 90';
22 END IF;
23
24 IF p_longitude < -180 OR p_longitude > 180 THEN
25 RAISE EXCEPTION 'Longitude must be between -180 and 180';
26 END IF;
27
28 IF p_max_distance_m <= 0 THEN
29 RAISE EXCEPTION 'Maximum distance must be positive';
30 END IF;
31
32 IF p_limit < 1 OR p_limit > 100 THEN
33 RAISE EXCEPTION 'Limit must be between 1 and 100';
34 END IF;
35
36 RETURN QUERY
37 WITH search_point AS
38 (
39 SELECT ST_SetSRID(ST_MakePoint(p_longitude, p_latitude), 4326) AS location
40 )
41 SELECT
42 ns.site_id,
43 ns.site_code,
44 ns.site_name,
45 ns.region,
46 round(
47 ST_Distance(ns.location::geography, sp.location::geography)::numeric,
48 1
49 ) AS distance_m,
50 coalesce(technologies.names, 'No active sectors') AS active_technologies
51 FROM public.network_sites ns
52 CROSS JOIN search_point sp
53 LEFT JOIN LATERAL
54 (
55 SELECT string_agg(
56 DISTINCT concat(nt.generation, ' ', nt.technology_name),
57 ', '
58 ORDER BY concat(nt.generation, ' ', nt.technology_name)
59 ) AS names
60 FROM public.cell_towers ct
61 JOIN public.tower_sectors ts ON ts.tower_id = ct.tower_id
62 JOIN public.network_technologies nt
63 ON nt.technology_id = ts.technology_id
64 WHERE ct.site_id = ns.site_id
65 AND ct.status = 'active'
66 AND ts.status = 'active'
67 AND nt.status = 'active'
68 ) technologies ON true
69 WHERE ns.status = 'active'
70 AND ns.location IS NOT NULL
71 AND ST_DWithin(
72 ns.location::geography,
73 sp.location::geography,
74 p_max_distance_m
75 )
76 ORDER BY ns.location::geography <-> sp.location::geography
77 LIMIT p_limit;
78END;
79$$;