| 1 | -- View 1
|
|---|
| 2 | create or replace view vw_worker_premium_analytics as
|
|---|
| 3 | select w.worker_id,
|
|---|
| 4 | date_trunc('month', py.payment_date) as month,
|
|---|
| 5 | pp.plan_id, pp.name AS plan_name,
|
|---|
| 6 | COUNT(pw.premium_id) filter ( where ps.status_name = 'Completed' ) as total_plans_bought,
|
|---|
| 7 | SUM(py.amount) filter ( where ps.status_name = 'Completed' ) as total_spent,
|
|---|
| 8 | MIN(pw.start_date) as first_plan_start,
|
|---|
| 9 | MAX(pw.end_date) as last_plan_end
|
|---|
| 10 | from Premium_Worker pw
|
|---|
| 11 | join Worker w on w.worker_id = pw.worker_id
|
|---|
| 12 | join Payment py on py.payment_id = pw.payment_id
|
|---|
| 13 | join Payment_Status ps on ps.status_id = py.payment_status
|
|---|
| 14 | join Worker_Method wm on wm.worker_method_id = py.worker_method_id
|
|---|
| 15 | join Premium_Plan pp on pp.plan_id = pw.plan_id
|
|---|
| 16 | group by w.worker_id, date_trunc('month', py.payment_date), pp.plan_id, pp.name;
|
|---|
| 17 |
|
|---|
| 18 | -- test
|
|---|
| 19 | select * from vw_worker_premium_analytics
|
|---|
| 20 | where worker_id = 6630371;
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 | -- View 2
|
|---|
| 26 | create or replace view vw_owner_payment_analytics_dashboard as
|
|---|
| 27 | with daily_stats as (
|
|---|
| 28 | select
|
|---|
| 29 | date_trunc('day', py.payment_date) as day,
|
|---|
| 30 | pm.method_id,
|
|---|
| 31 | pm.method_name,
|
|---|
| 32 | pm.tax,
|
|---|
| 33 | COUNT(py.payment_id) as n_per_method_per_day,
|
|---|
| 34 | SUM(py.amount) as t_per_method_day
|
|---|
| 35 | from Payment py
|
|---|
| 36 | join Payment_Status ps on ps.status_id = py.payment_status
|
|---|
| 37 | join Worker_Method wm on wm.worker_method_id = py.worker_method_id
|
|---|
| 38 | join Payment_Method pm on pm.method_id = wm.method_id
|
|---|
| 39 | where ps.status_name = 'Completed'
|
|---|
| 40 | group by date_trunc('day', py.payment_date), pm.method_id, pm.method_name, pm.tax
|
|---|
| 41 | ), ranked as (
|
|---|
| 42 | select *,
|
|---|
| 43 | SUM(n_per_method_per_day) over (partition by day) as t_n_payments_day,
|
|---|
| 44 | SUM(t_per_method_day) over (partition by day) as t_amount_day,
|
|---|
| 45 | SUM(t_per_method_day * tax) OVER (partition by day) as t_tax_day,
|
|---|
| 46 | ROW_NUMBER() over (partition by day ORDER BY n_per_method_per_day desc) as rn
|
|---|
| 47 | from daily_stats
|
|---|
| 48 | )
|
|---|
| 49 | select
|
|---|
| 50 | day,
|
|---|
| 51 | t_amount_day as total_earned,
|
|---|
| 52 | t_n_payments_day as total_transactions,
|
|---|
| 53 | ROUND(t_tax_day::NUMERIC, 2) as total_tax_collected,
|
|---|
| 54 | method_id as most_used_method_id,
|
|---|
| 55 | method_name as most_used_method,
|
|---|
| 56 | ROUND((n_per_method_per_day::NUMERIC / NULLIF(t_n_payments_day, 0)) * 100, 2) as most_used_method_pct
|
|---|
| 57 | from ranked
|
|---|
| 58 | where rn = 1;
|
|---|
| 59 |
|
|---|
| 60 | -- test
|
|---|
| 61 | select * from vw_owner_payment_analytics_dashboard
|
|---|
| 62 | where day = '2024-11-17 00:00:00.000';
|
|---|
| 63 |
|
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 |
|
|---|
| 69 | -- View 3
|
|---|
| 70 | create or replace view vw_review_analytics as
|
|---|
| 71 | select
|
|---|
| 72 | ws.worker_id,
|
|---|
| 73 | u.username,
|
|---|
| 74 | s.specialty_name,
|
|---|
| 75 | ws.specialty_id,
|
|---|
| 76 | (
|
|---|
| 77 | select avg(r.grade)
|
|---|
| 78 | from Review r
|
|---|
| 79 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 80 | ) as avg_grade,
|
|---|
| 81 | (
|
|---|
| 82 | select count(*)
|
|---|
| 83 | from Review r
|
|---|
| 84 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 85 | ) as total_reviews,
|
|---|
| 86 | (
|
|---|
| 87 | select count(*)
|
|---|
| 88 | from Review_Comment rc
|
|---|
| 89 | where rc.review_id in (
|
|---|
| 90 | select r.review_id
|
|---|
| 91 | from Review r
|
|---|
| 92 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 93 | )
|
|---|
| 94 | ) as total_comments,
|
|---|
| 95 | (
|
|---|
| 96 | select count(*)
|
|---|
| 97 | from Review r
|
|---|
| 98 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 99 | and r.grade = 1
|
|---|
| 100 | ) as one_star,
|
|---|
| 101 | (
|
|---|
| 102 | select count(*)
|
|---|
| 103 | from Review r
|
|---|
| 104 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 105 | and r.grade = 2
|
|---|
| 106 | ) as two_star,
|
|---|
| 107 | (
|
|---|
| 108 | select count(*)
|
|---|
| 109 | from Review r
|
|---|
| 110 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 111 | and r.grade = 3
|
|---|
| 112 | ) as three_star,
|
|---|
| 113 | (
|
|---|
| 114 | select count(*)
|
|---|
| 115 | from Review r
|
|---|
| 116 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 117 | and r.grade = 4
|
|---|
| 118 | ) as four_star,
|
|---|
| 119 | (
|
|---|
| 120 | select count(*)
|
|---|
| 121 | from Review r
|
|---|
| 122 | where r.worker_specialty_id = ws.worker_specialty_id
|
|---|
| 123 | and r.grade = 5
|
|---|
| 124 | ) as five_star
|
|---|
| 125 | from Worker_Specialty ws
|
|---|
| 126 | join specialty s on ws.specialty_id = s.specialty_id
|
|---|
| 127 | join worker w on ws.worker_id = w.worker_id
|
|---|
| 128 | join "User" u on u.user_id = w.user_id;
|
|---|
| 129 |
|
|---|
| 130 | -- test
|
|---|
| 131 | select * from vw_review_analytics
|
|---|
| 132 | where worker_id = 6630378;
|
|---|
| 133 |
|
|---|
| 134 |
|
|---|
| 135 |
|
|---|
| 136 |
|
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 |
|
|---|
| 140 | -- View 4
|
|---|
| 141 | create or replace view vw_worker_aggregate as
|
|---|
| 142 | select
|
|---|
| 143 | w.worker_id,
|
|---|
| 144 | u.first_name,
|
|---|
| 145 | u.last_name,
|
|---|
| 146 | u.username,
|
|---|
| 147 | count(distinct a.application_id) as total_applications,
|
|---|
| 148 | count(distinct a.application_id) filter (where apps.status_name = 'Accepted') as accepted_applications,
|
|---|
| 149 | count(distinct a.application_id) filter (where apps.status_name = 'Rejected') as rejected_applications,
|
|---|
| 150 |
|
|---|
| 151 | round(count(distinct a.application_id) filter (
|
|---|
| 152 | where apps.status_name = 'Accepted'
|
|---|
| 153 | )::numeric / count(distinct a.application_id)*100,2) as accepted_percentage,
|
|---|
| 154 |
|
|---|
| 155 | round(count(distinct a.application_id) filter (
|
|---|
| 156 | where apps.status_name = 'Rejected'
|
|---|
| 157 | )::numeric / count(distinct a.application_id)*100,2) as rejected_percentage,
|
|---|
| 158 |
|
|---|
| 159 | count(distinct a.application_id) filter (
|
|---|
| 160 | where apps.status_name = 'Accepted'and ps.status_name = 'Completed'
|
|---|
| 161 | ) as completed_jobs
|
|---|
| 162 |
|
|---|
| 163 | from worker w
|
|---|
| 164 | join "User" u on u.user_id= w.user_id
|
|---|
| 165 | join application a on a.worker_id= w.worker_id
|
|---|
| 166 | join application_status apps on apps.status_id = a.status_id
|
|---|
| 167 | join post po on po.post_id = a.post_id
|
|---|
| 168 | join post_status ps on ps.status_id = po.status_id
|
|---|
| 169 | group by w.worker_id, u.first_name, u.last_name, u.username;
|
|---|
| 170 |
|
|---|
| 171 | -- test
|
|---|
| 172 | select *
|
|---|
| 173 | from vw_worker_aggregate
|
|---|
| 174 | where worker_id = 6630378;
|
|---|
| 175 |
|
|---|
| 176 | insert into application (message, needed_time, expected_price, created_at, worker_id, post_id, status_id)
|
|---|
| 177 | values ('Adding a new application', '01:00:00', 5000, '2023-06-22 14:00:03.945', 6722966, 4137859, 3)
|
|---|
| 178 | update Application set expected_price=5509 where application_id = 8308242;
|
|---|
| 179 |
|
|---|
| 180 | -- index
|
|---|
| 181 | create index idx_application_worker_id on application(worker_id);
|
|---|
| 182 |
|
|---|
| 183 |
|
|---|
| 184 |
|
|---|
| 185 |
|
|---|
| 186 |
|
|---|
| 187 | -- View 5
|
|---|
| 188 |
|
|---|
| 189 | create materialized view vw_app_aggregate as
|
|---|
| 190 | select
|
|---|
| 191 | count(distinct u.user_id) as total_users,
|
|---|
| 192 | count(distinct p.post_id) as total_posts,
|
|---|
| 193 | count(distinct p.post_id) filter (where ps.status_name = 'Active') as active_posts,
|
|---|
| 194 | count(distinct p.post_id) filter (where ps.status_name = 'Completed') as completed_posts,
|
|---|
| 195 | count(distinct p.post_id) filter (where ps.status_name = 'Deleted') as deleted_posts,
|
|---|
| 196 | round(count(distinct p.post_id) filter (where ps.status_name = 'Active')::numeric
|
|---|
| 197 | / count(distinct p.post_id) * 100, 2) as active_post_pct,
|
|---|
| 198 | count(distinct a.application_id) as total_applications,
|
|---|
| 199 | (select max(p2.created_at) from post p2) as latest_post_date
|
|---|
| 200 | from "User" u
|
|---|
| 201 | left join post p on p.user_id = u.user_id
|
|---|
| 202 | left join post_status ps on ps.status_id = p.status_id
|
|---|
| 203 | left join application a on a.post_id = p.post_id;
|
|---|
| 204 |
|
|---|
| 205 | -- test
|
|---|
| 206 | select *
|
|---|
| 207 | from vw_app_aggregate;
|
|---|
| 208 |
|
|---|
| 209 | insert into post (title, description, created_at, user_id, location_id, status_id)
|
|---|
| 210 | values ('Needing a plumber', 'The bath is leaking', '2024-03-07 18:52:55.693', 503189, 9199, 2)
|
|---|
| 211 |
|
|---|
| 212 | update post
|
|---|
| 213 | set description = 'The bath is leaking from the bottom'
|
|---|
| 214 | where user_id = 503189 and created_at = '2024-03-07 18:52:55.693'
|
|---|
| 215 |
|
|---|
| 216 |
|
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 |
|
|---|
| 220 |
|
|---|
| 221 | -- View 6
|
|---|
| 222 | create or replace view vw_location_aggregate as
|
|---|
| 223 | select
|
|---|
| 224 | l.location_id,
|
|---|
| 225 | l.city,
|
|---|
| 226 | l.region,
|
|---|
| 227 | count(distinct p.post_id) as total_posts,
|
|---|
| 228 | count(distinct p.post_id) filter (where ps.status_name = 'Active') as active_posts,
|
|---|
| 229 | count(distinct p.post_id) filter (where ps.status_name = 'Completed') as completed_posts,
|
|---|
| 230 | count(distinct w.worker_id) as total_workers,
|
|---|
| 231 | count(distinct w.worker_id) filter (where w.works_remote = true) as remote_workers
|
|---|
| 232 | from location l
|
|---|
| 233 | left join post p on p.location_id= l.location_id
|
|---|
| 234 | left join post_status ps on ps.status_id = p.status_id
|
|---|
| 235 | left join worker w on w.location_id = l.location_id
|
|---|
| 236 | group by l.location_id, l.city, l.region;
|
|---|
| 237 |
|
|---|
| 238 | --test
|
|---|
| 239 | select *
|
|---|
| 240 | from vw_location_aggregate
|
|---|
| 241 | where location_id = 7;
|
|---|
| 242 |
|
|---|
| 243 | -- index
|
|---|
| 244 | create index idx_post_location on Post(location_id);
|
|---|
| 245 |
|
|---|
| 246 |
|
|---|
| 247 |
|
|---|
| 248 |
|
|---|
| 249 |
|
|---|
| 250 |
|
|---|
| 251 |
|
|---|
| 252 | -- View 7
|
|---|
| 253 | create or replace view vw_post_full_details as
|
|---|
| 254 | select p.post_id, p.title, p.description, p.created_at,
|
|---|
| 255 | ps.status_name,
|
|---|
| 256 | u.user_id, u.first_name, u.last_name, u.username,
|
|---|
| 257 | l.city, l.region, l.address,
|
|---|
| 258 |
|
|---|
| 259 | array_agg(distinct s.specialty_name) as specialties,
|
|---|
| 260 | array_agg(distinct pi.image_id) as image_ids,
|
|---|
| 261 | count(distinct a.application_id) as total_applications,
|
|---|
| 262 | count(distinct a.application_id) filter ( where apps.status_name = 'Accepted') as accepted_applications,
|
|---|
| 263 | count(distinct a.application_id) filter (where apps.status_name = 'Rejected') as rejected_applications,
|
|---|
| 264 | round(avg(a.expected_price)::numeric, 2) as avg_expected_price,
|
|---|
| 265 | min(a.expected_price) as min_expected_price,
|
|---|
| 266 | max(a.expected_price) as max_expected_price
|
|---|
| 267 |
|
|---|
| 268 | from post p
|
|---|
| 269 | join post_status ps on ps.status_id = p.status_id
|
|---|
| 270 | join "User" u on u.user_id = p.user_id
|
|---|
| 271 | join location l on l.location_id = p.location_id
|
|---|
| 272 | join post_specialty psp on psp.post_id = p.post_id
|
|---|
| 273 | join specialty s on s.specialty_id = psp.specialty_id
|
|---|
| 274 | join post_image pi on pi.post_id = p.post_id
|
|---|
| 275 | join application a on a.post_id = p.post_id
|
|---|
| 276 | join application_status apps on apps.status_id = a.status_id
|
|---|
| 277 |
|
|---|
| 278 | group by p.post_id, p.title, p.description, p.created_at,
|
|---|
| 279 | ps.status_name,
|
|---|
| 280 | u.user_id, u.first_name, u.last_name, u.username,
|
|---|
| 281 | l.city, l.region, l.address;
|
|---|
| 282 |
|
|---|
| 283 | -- test
|
|---|
| 284 | select *
|
|---|
| 285 | from vw_post_full_details
|
|---|
| 286 | where post_id = 1539670;
|
|---|
| 287 |
|
|---|
| 288 | insert into Post_Specialty(post_id, specialty_id)
|
|---|
| 289 | values (919803, 1);
|
|---|
| 290 |
|
|---|
| 291 | insert into Post_Image(image_file, post_id)
|
|---|
| 292 | values ('x48562878a554caab5dd263b0e66a3ff246d272d4988137609211e640faddb168967b0ae78a446bebbd26b6c6386d548e8f38474363c68595cf054f3a212ebae567640dc8227c9fd60a17bb3c59226226ba83612c47e89d3c02c68350a1f025a4d1d8d1356894e72614763be27b43f84208d1f08e07ff92e9b6f524e8da169885b41621dbdd1438376bb0215285e1ff3817ffce1dbe2eb04d3a8d9ba5078f853e3b7eb87d9343b0c0741c788e669a2b16d5d616675c16c53798dbfee28139377bc15f99f7fe10e382162519eda8f81a7301371f33c9fd857605c5a30135ff4fd2015cf7fc8675971d448a197c5c6d91857b35ab3601d5c5b3e8722da96c3cc93eaf31f7569e864e9e628421b6338e0491cbe407a3243452ee2007a4fe4c20f6c91c50be875b6178f04605c8fc3b762700d12255c916f35e2e9367fa9798fecf5a88fe3d9c1b0d1154b3779fde45bd44376de95dc5eea787bb868f23c14adf8870035acad57427cf33854b47361d57d5fdcde2b187105373f3b93916efe20fa708af47f74ff04a748575e9594dffc4c8296f6182c27179430faf22286825f378a6fe78d23f2bab6ef1b5e762909bd1dc14bc0f7eaff94d8f9e34a03d6a74782241064b89514fe6a7617a0c4d71d25d906ecf7eec27cfa34728fce19acb70f36210214a54f53c191d0ddc0236586fce596f55b714073af9ffd8e1db90b732c846cbd01867dd0f15652110a336814085a5607e986d489440f7a83e4a9fac17b3918abee978fab3a855ae38e0a7a83ef84e1032191f560f2f6c82f82dad394c54df376bfecfcc8ca65f384742d46756a4d0a25382e33f6c90f50be4fb2e13cbcab91e420ae3c8a6dc2f72fa11f1e8cafce053c7e04ecfb522e5f31de9676b5aaafa2685c2cc4c900a4e43f3d7fd6554f414a594392522cbe7fba08eb640e7331e1c12451437fd0ffe553fe873076428ba59ca433de619e792daa20aa67e9b6c95e4535c8abd1fa3bd2c77255bac6e25250174cc146107e6969425c1472fe43df4f2544984205f2d239f92210bb5f2bf6227571f47b0d4ed375b8586d9bc247dce226d0775423651f0cc5680ea32b94f3cdac65046ff82cc1127be50dafced937f70c4a4ac39fa2636f3b13378fac28398f9f0b44a52683613ed6e5e61fa8c83b0604ac7459d55d67ee5d5983b9cdf068cef996d87546ed39080af3fd2124f7cb702f8a3c405a0a28374dcb0f71a8c2fc5fc6bc9d15e3f8b88c535dc5347831f59b23adf1ea9ca691bc2a554dd27c507db2752601958732b19ac3763a5aac25abcc14278e6a02a5c891f1162db132aeebd49e3ea61ce0405638b8a1e71a968d85ded791480b956e4e0c2729e1bcb1bb4156ea8fc320d94626ce714f575b7e0e34a75ec62074259bc8cb91869b7910407538b2f710fd6c8a1bd8bd114551765384d12e9b8ff06a40c85461a45d5da8ffede03ebbc6a6e37fb258d68bf95c331a2fd86d36b1d3a96c813e0fa2ce29dc4c64b17d4ef1aeb7bd2a73a5405e91bc63585d7fa5597a7e8b297a5f2ba6a2b882f12f5a81f', 1863168);
|
|---|
| 293 |
|
|---|
| 294 | --index
|
|---|
| 295 | create index idx_application_post_id on Application(post_id);
|
|---|
| 296 | create index idx_post_specialty_post_id on Post_Specialty(post_id);
|
|---|
| 297 | create index idx_post_image_post_id on Post_Image(post_id);
|
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 |
|
|---|
| 301 |
|
|---|
| 302 |
|
|---|
| 303 |
|
|---|
| 304 |
|
|---|
| 305 | -- View 8
|
|---|
| 306 | create or replace view vw_user_notifications as
|
|---|
| 307 | select
|
|---|
| 308 | u.user_id,
|
|---|
| 309 | u.first_name,
|
|---|
| 310 | u.last_name,
|
|---|
| 311 | u.username,
|
|---|
| 312 | n.notification_id,
|
|---|
| 313 | n.message,
|
|---|
| 314 | n.is_read,
|
|---|
| 315 | n.created_at as notification_created_at
|
|---|
| 316 | from "User" u
|
|---|
| 317 | join notification n on n.user_id = u.user_id
|
|---|
| 318 | order by n.created_at desc
|
|---|
| 319 |
|
|---|
| 320 | -- test
|
|---|
| 321 | select *
|
|---|
| 322 | from vw_user_notifications
|
|---|
| 323 | where user_id = 903515;
|
|---|
| 324 |
|
|---|
| 325 | insert into notification(message, is_read, created_at, user_id)
|
|---|
| 326 | values ('New worker has sent you an application', false, '2026-03-13 02:20:26.203', 210032)
|
|---|
| 327 |
|
|---|
| 328 | update notification
|
|---|
| 329 | set is_read = true
|
|---|
| 330 | where user_id = 210032 and created_at = '2026-03-13 02:20:26.203'
|
|---|
| 331 |
|
|---|
| 332 |
|
|---|
| 333 |
|
|---|
| 334 |
|
|---|
| 335 |
|
|---|
| 336 |
|
|---|
| 337 |
|
|---|
| 338 |
|
|---|
| 339 | -- View 9
|
|---|
| 340 | create or replace view vw_worker_applications as
|
|---|
| 341 | select
|
|---|
| 342 | w.worker_id,
|
|---|
| 343 | u.first_name,
|
|---|
| 344 | u.last_name,
|
|---|
| 345 | a.application_id,
|
|---|
| 346 | a.message,
|
|---|
| 347 | a.expected_price,
|
|---|
| 348 | a.needed_time,
|
|---|
| 349 | a.created_at,
|
|---|
| 350 | apps.status_name as application_status,
|
|---|
| 351 | p.post_id,
|
|---|
| 352 | p.title as post_title,
|
|---|
| 353 | p.description as post_description,
|
|---|
| 354 | ps.status_name as post_status,
|
|---|
| 355 | l.city,
|
|---|
| 356 | l.region
|
|---|
| 357 | from worker w
|
|---|
| 358 | join "User" u on u.user_id = w.user_id
|
|---|
| 359 | join application a on a.worker_id = w.worker_id
|
|---|
| 360 | join application_status apps on apps.status_id = a.status_id
|
|---|
| 361 | join post p on p.post_id = a.post_id
|
|---|
| 362 | join post_status ps on ps.status_id = p.status_id
|
|---|
| 363 | left join location l on l.location_id = p.location_id;
|
|---|
| 364 |
|
|---|
| 365 | -- test
|
|---|
| 366 | select *
|
|---|
| 367 | from vw_worker_applications
|
|---|
| 368 | where worker_id = 6630371;
|
|---|
| 369 |
|
|---|
| 370 |
|
|---|