AdvancedTopic: MajStore_PostGis.sql

File MajStore_PostGis.sql, 9.1 KB (added by 231049, 6 days ago)
Line 
1CREATE EXTENSION IF NOT EXISTS postgis;
2
3alter table location add column geom GEOMETRY(Point, 4326);
4update location set geom = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326);
5
6create index idx_location_geom on Location USING GIST(geom);
7
8
9-- WORKER
10-- 1
11create or replace function fn_suggest_posts_for_worker(p_worker_id int, p_limit int default 10)
12 returns table (post_id int, title text, distance_meters float)
13 language plpgsql
14as
15$$
16declare
17 v_works_remote bool;
18begin
19 select w.works_remote
20 into v_works_remote
21 from worker w
22 where w.worker_id = p_worker_id;
23
24 return query
25 select p.post_id,
26 p.title,
27 ST_Distance(worker_loc.geom::geography, post_loc.geom::geography)::float as distance_meters
28 from worker w
29 join location worker_loc on w.location_id = worker_loc.location_id
30 join post p on p.status_id = 1
31 join location post_loc on p.location_id = post_loc.location_id
32 where w.worker_id = p_worker_id
33 and exists(select 1
34 from worker_specialty ws
35 join post_specialty ps on ws.specialty_id = ps.specialty_id
36 where ws.worker_id = w.worker_id and ps.post_id = p.post_id)
37 and (v_works_remote = true or ST_DWithin(worker_loc.geom::geography, post_loc.geom::geography, 1500))
38 and p.status_id = 1
39 order by worker_loc.geom <-> post_loc.geom
40 limit p_limit;
41end;
42$$;
43
44select * from fn_suggest_posts_for_worker(6630361, 10); -- works remote = false
45select * from fn_suggest_posts_for_worker(6630362, 10000); -- works remote = true
46
47
48
49
50
51
52
53
54-- 2
55create or replace function fn_draw_worker_location(p_worker_id integer)
56 returns table(worker_id integer, geom geometry)
57 language plpgsql
58as $$
59begin
60 return query
61 select
62 w.worker_id,
63 l.geom
64 from worker w
65 join location l on w.location_id = l.location_id
66 where w.worker_id = p_worker_id;
67end;
68$$;
69
70select * from fn_draw_worker_location(6630361);
71select * from fn_draw_worker_location(6630362);
72
73
74
75
76
77
78-- 3
79create or replace function fn_draw_active_posts_in_worker_region(p_worker_id integer, p_limit int default 10)
80 returns table(post_id integer, title text, distance float, geom geometry)
81 language plpgsql
82as $$
83 declare v_works_remote bool;
84begin
85 select w.works_remote into v_works_remote
86 from worker w
87 where w.worker_id = p_worker_id;
88
89 return query
90 select
91 p.post_id,
92 p.title,
93 ST_DISTANCE(worker_loc.geom::geography, post_loc.geom::geography)::float as distance_m,
94 post_loc.geom as geom
95 from worker w
96 join location worker_loc on w.location_id = worker_loc.location_id
97 join post p on p.status_id = 1
98 join location post_loc on p.location_id = post_loc.location_id
99 join post_status s on p.status_id = s.status_id
100 where w.worker_id = p_worker_id
101 and s.status_name = 'Active'
102 and exists (
103 select 1
104 from worker_specialty ws
105 join post_specialty ps on ws.specialty_id = ps.specialty_id
106 where ws.worker_id = w.worker_id
107 and ps.post_id = p.post_id
108 )
109 and (v_works_remote = true or ST_DWITHIN(worker_loc.geom::geography, post_loc.geom::geography, 1500))
110 order by worker_loc.geom <-> post_loc.geom
111 limit p_limit;
112end;
113$$;
114
115select * from fn_draw_active_posts_in_worker_region(6630361); -- works remote = false
116select * from fn_draw_active_posts_in_worker_region(6630362); -- works remote = true
117
118
119
120
121
122-- 4
123create or replace function fn_draw_worker_to_post_lines(p_worker_id integer,p_limit int default 10)
124 returns table(post_id integer, title text, distance_m float, geom geometry)
125 language plpgsql
126as $$
127 declare v_works_remote bool;
128begin
129 select w.works_remote into v_works_remote
130 from worker w
131 where w.worker_id = p_worker_id;
132 return query
133 select
134 p.post_id,
135 p.title,
136 st_distance(worker_loc.geom::geography, post_loc.geom::geography)::float as distance_m,
137 st_makeline(worker_loc.geom, post_loc.geom) as geom
138 from worker w
139 join location worker_loc on w.location_id = worker_loc.location_id
140 join post p on p.status_id = 1
141 join location post_loc on p.location_id = post_loc.location_id
142 join post_status s on p.status_id = s.status_id
143 where w.worker_id = p_worker_id
144 and s.status_name = 'Active'
145 and exists (
146 select 1
147 from worker_specialty ws
148 join post_specialty ps on ws.specialty_id = ps.specialty_id
149 where ws.worker_id = w.worker_id
150 and ps.post_id = p.post_id)
151 and (v_works_remote = true or st_dwithin(worker_loc.geom::geography, post_loc.geom::geography, 1500))
152 order by worker_loc.geom <-> post_loc.geom
153 limit p_limit;
154end;
155$$;
156
157select * from fn_draw_worker_to_post_lines(6630361); -- works remote = false
158select * from fn_draw_worker_to_post_lines(6630362); -- works remote = true
159
160
161
162
163
164
165
166-- 5
167create or replace function fn_draw_worker_notRemote_region(p_worker_id integer)
168 returns table(worker_id integer, geom geometry)
169 language plpgsql
170as $$
171declare
172 v_works_remote bool;
173begin
174 select w.works_remote into v_works_remote
175 from worker w
176 where w.worker_id = p_worker_id;
177
178 if v_works_remote = true then
179 return;
180 end if;
181
182 return query
183 select
184 w.worker_id,
185 ST_Buffer(
186 l.geom::geography,
187 1000
188 )::geometry as geom
189 from worker w
190 join location l on w.location_id = l.location_id
191 where w.worker_id = p_worker_id;
192end;
193$$;
194
195select * from fn_draw_worker_notRemote_region(6630361); -- works remote = false
196select * from fn_draw_worker_notRemote_region(6630362); -- works remote = true
197
198
199
200
201
202-- POST
203-- 6
204create or replace function fn_application_workers_for_post(p_post_id int, p_limit int default 10)
205 returns table(worker_id int, first_name text, last_name text, bio text, distance_meters float)
206language plpgsql as $$
207begin
208 return query
209 select w.worker_id, u.first_name, u.last_name, a.message,
210 ST_Distance(worker_loc.geom::geography, post_loc.geom::geography)::float as distance_meters
211 from worker w
212 join "User" u on w.user_id = u.user_id
213 join location worker_loc on w.location_id = worker_loc.location_id
214 join post p on p.post_id = p_post_id
215 join application a on p.post_id = a.post_id and a.worker_id = w.worker_id
216 join location post_loc on p.location_id = post_loc.location_id
217 where (w.works_remote = true
218 or ST_DWithin(worker_loc.geom::geography, post_loc.geom::geography, 1500))
219 and p.status_id = 1
220
221 order by worker_loc.geom <-> post_loc.geom
222 limit p_limit;
223end;
224$$;
225
226select * from fn_application_workers_for_post(1787990);
227
228
229
230-- 7
231create or replace function fn_draw_post_location(p_post_id integer)
232 returns table(post_id integer, title text, geom geometry)
233 language plpgsql
234as $$
235begin
236 return query
237 select
238 p.post_id,
239 p.title,
240 l.geom
241 from post p
242 join location l on p.location_id = l.location_id
243 where p.post_id = p_post_id;
244end;
245$$;
246
247select * from fn_draw_post_location(1787990);
248
249
250
251
252
253
254
255
256
257-- 8
258create or replace function fn_draw_workers_applied_to_post(p_post_id integer,p_limit int default 10)
259 returns table(worker_id integer, distance_m float, geom geometry)
260 language plpgsql
261as $$
262begin
263 return query
264 select
265 w.worker_id,
266 st_distance(post_loc.geom::geography, worker_loc.geom::geography)::float as distance_m,
267 worker_loc.geom as geom
268 from post p
269 join location post_loc on p.location_id = post_loc.location_id
270 join application a on a.post_id = p.post_id
271 join worker w on w.worker_id = a.worker_id
272 join location worker_loc on w.location_id = worker_loc.location_id
273 where p.post_id = p_post_id
274 order by post_loc.geom <-> worker_loc.geom
275 limit p_limit;
276end;
277$$;
278
279select * from fn_draw_workers_applied_to_post(1787990);
280
281
282
283
284
285-- 9
286create or replace function fn_draw_post_to_applicant_lines(p_post_id integer,p_limit int default 10)
287 returns table(worker_id integer, distance_m float, geom geometry)
288 language plpgsql
289as $$
290begin
291 return query
292 select
293 w.worker_id,
294 st_distance(post_loc.geom::geography, worker_loc.geom::geography)::float as distance_m,
295 st_makeline(post_loc.geom, worker_loc.geom) as geom
296 from post p
297 join location post_loc on p.location_id = post_loc.location_id
298 join application a on a.post_id = p.post_id
299 join worker w on w.worker_id = a.worker_id
300 join location worker_loc on w.location_id = worker_loc.location_id
301 where p.post_id = p_post_id
302 order by post_loc.geom <-> worker_loc.geom
303 limit p_limit;
304end;
305$$;
306
307select * from fn_draw_post_to_applicant_lines(1787990);
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323