source: database/migrations/0000_colorful_scream.sql

main
Last change on this file was ff3a614, checked in by Tome <gjorgievtome@…>, 4 months ago

Fix SQL functions for reporting and update queries in reports

  • Property mode set to 100644
File size: 24.2 KB
Line 
1CREATE TABLE "build_component" (
2 "build_id" integer NOT NULL,
3 "component_id" integer NOT NULL,
4 "num_components" integer DEFAULT 1 NOT NULL,
5 CONSTRAINT "build_component_build_id_component_id_pk" PRIMARY KEY("build_id","component_id")
6);
7--> statement-breakpoint
8CREATE TABLE "build" (
9 "id" serial PRIMARY KEY NOT NULL,
10 "user_id" integer NOT NULL,
11 "name" text NOT NULL,
12 "created_at" date NOT NULL,
13 "description" text,
14 "total_price" numeric NOT NULL,
15 "is_approved" boolean NOT NULL
16);
17--> statement-breakpoint
18CREATE TABLE "favorite_build" (
19 "build_id" integer NOT NULL,
20 "user_id" integer NOT NULL,
21 CONSTRAINT "favorite_build_build_id_user_id_pk" PRIMARY KEY("build_id","user_id")
22);
23--> statement-breakpoint
24CREATE TABLE "rating_build" (
25 "build_id" integer NOT NULL,
26 "user_id" integer NOT NULL,
27 "value" numeric NOT NULL,
28 CONSTRAINT "rating_build_build_id_user_id_pk" PRIMARY KEY("build_id","user_id"),
29 CONSTRAINT "check_value" CHECK ("rating_build"."value" BETWEEN 1 AND 5)
30);
31--> statement-breakpoint
32CREATE TABLE "review" (
33 "id" serial PRIMARY KEY NOT NULL,
34 "build_id" integer NOT NULL,
35 "user_id" integer NOT NULL,
36 "content" text NOT NULL,
37 "created_at" date NOT NULL,
38 CONSTRAINT "review_build_id_user_id_unique" UNIQUE("build_id","user_id")
39);
40--> statement-breakpoint
41CREATE TABLE "cpu" (
42 "component_id" integer PRIMARY KEY NOT NULL,
43 "socket" text NOT NULL,
44 "cores" integer NOT NULL,
45 "threads" integer NOT NULL,
46 "base_clock" numeric NOT NULL,
47 "boost_clock" numeric,
48 "tdp" numeric NOT NULL
49);
50--> statement-breakpoint
51CREATE TABLE "gpu" (
52 "component_id" integer PRIMARY KEY NOT NULL,
53 "vram" numeric NOT NULL,
54 "tdp" numeric NOT NULL,
55 "base_clock" numeric,
56 "boost_clock" numeric,
57 "chipset" text NOT NULL,
58 "length" numeric NOT NULL
59);
60--> statement-breakpoint
61CREATE TABLE "cables" (
62 "component_id" integer PRIMARY KEY NOT NULL,
63 "length_cm" numeric NOT NULL,
64 "type" text NOT NULL
65);
66--> statement-breakpoint
67CREATE TABLE "case_mobo_form_factors" (
68 "case_id" integer NOT NULL,
69 "form_factor" text NOT NULL,
70 CONSTRAINT "case_mobo_form_factors_case_id_form_factor_pk" PRIMARY KEY("case_id","form_factor")
71);
72--> statement-breakpoint
73CREATE TABLE "case_ps_form_factors" (
74 "case_id" integer NOT NULL,
75 "form_factor" text NOT NULL,
76 CONSTRAINT "case_ps_form_factors_case_id_form_factor_pk" PRIMARY KEY("case_id","form_factor")
77);
78--> statement-breakpoint
79CREATE TABLE "case_storage_form_factors" (
80 "case_id" integer NOT NULL,
81 "form_factor" text NOT NULL,
82 "num_slots" integer NOT NULL,
83 CONSTRAINT "case_storage_form_factors_case_id_form_factor_pk" PRIMARY KEY("case_id","form_factor")
84);
85--> statement-breakpoint
86CREATE TABLE "components" (
87 "id" serial PRIMARY KEY NOT NULL,
88 "name" text NOT NULL,
89 "brand" text NOT NULL,
90 "price" numeric NOT NULL,
91 "img_url" text,
92 "type" text NOT NULL,
93 CONSTRAINT "check_type" CHECK ("components"."type" in
94 ('cpu', 'gpu', 'memory', 'storage', 'power_supply', 'motherboard', 'case', 'cooler', 'memory_card', 'optical_drive', 'sound_card', 'cables', 'network_adapter', 'network_card'))
95);
96--> statement-breakpoint
97CREATE TABLE "cooler_cpu_sockets" (
98 "cooler_id" integer NOT NULL,
99 "socket" text NOT NULL,
100 CONSTRAINT "cooler_cpu_sockets_cooler_id_socket_pk" PRIMARY KEY("cooler_id","socket")
101);
102--> statement-breakpoint
103CREATE TABLE "cooler" (
104 "component_id" integer PRIMARY KEY NOT NULL,
105 "type" text NOT NULL,
106 "height" numeric NOT NULL,
107 "max_tdp_supported" numeric NOT NULL
108);
109--> statement-breakpoint
110CREATE TABLE "memory_card" (
111 "component_id" integer PRIMARY KEY NOT NULL,
112 "num_slots" integer NOT NULL,
113 "interface" text NOT NULL
114);
115--> statement-breakpoint
116CREATE TABLE "memory" (
117 "component_id" integer PRIMARY KEY NOT NULL,
118 "type" text NOT NULL,
119 "speed" numeric NOT NULL,
120 "capacity" numeric NOT NULL,
121 "modules" integer NOT NULL
122);
123--> statement-breakpoint
124CREATE TABLE "motherboard" (
125 "component_id" integer PRIMARY KEY NOT NULL,
126 "socket" text NOT NULL,
127 "chipset" text NOT NULL,
128 "form_factor" text NOT NULL,
129 "ram_type" text NOT NULL,
130 "num_ram_slots" integer NOT NULL,
131 "max_ram_capacity" numeric NOT NULL,
132 "pci_express_slots" numeric NOT NULL
133);
134--> statement-breakpoint
135CREATE TABLE "network_adapter" (
136 "component_id" integer PRIMARY KEY NOT NULL,
137 "wifi_version" text NOT NULL,
138 "interface" text NOT NULL,
139 "num_antennas" integer NOT NULL
140);
141--> statement-breakpoint
142CREATE TABLE "network_card" (
143 "component_id" integer PRIMARY KEY NOT NULL,
144 "num_ports" integer NOT NULL,
145 "speed" numeric NOT NULL,
146 "interface" text NOT NULL
147);
148--> statement-breakpoint
149CREATE TABLE "optical_drive" (
150 "component_id" integer PRIMARY KEY NOT NULL,
151 "form_factor" text NOT NULL,
152 "type" text NOT NULL,
153 "interface" text NOT NULL,
154 "write_speed" numeric NOT NULL,
155 "read_speed" numeric NOT NULL
156);
157--> statement-breakpoint
158CREATE TABLE "pc_case" (
159 "component_id" integer PRIMARY KEY NOT NULL,
160 "cooler_max_height" numeric NOT NULL,
161 "gpu_max_length" numeric NOT NULL
162);
163--> statement-breakpoint
164CREATE TABLE "power_supply" (
165 "component_id" integer PRIMARY KEY NOT NULL,
166 "type" text NOT NULL,
167 "wattage" numeric NOT NULL,
168 "form_factor" text NOT NULL
169);
170--> statement-breakpoint
171CREATE TABLE "sound_card" (
172 "component_id" integer PRIMARY KEY NOT NULL,
173 "sample_rate" numeric NOT NULL,
174 "bit_depth" numeric NOT NULL,
175 "chipset" text NOT NULL,
176 "interface" text NOT NULL,
177 "channel" text NOT NULL
178);
179--> statement-breakpoint
180CREATE TABLE "storage" (
181 "component_id" integer PRIMARY KEY NOT NULL,
182 "type" text NOT NULL,
183 "capacity" numeric NOT NULL,
184 "form_factor" text NOT NULL
185);
186--> statement-breakpoint
187CREATE TABLE "admins" (
188 "user_id" integer PRIMARY KEY NOT NULL
189);
190--> statement-breakpoint
191CREATE TABLE "suggestions" (
192 "id" serial PRIMARY KEY NOT NULL,
193 "user_id" integer NOT NULL,
194 "admin_id" integer,
195 "link" text NOT NULL,
196 "admin_comment" text,
197 "description" text,
198 "status" text DEFAULT 'pending' NOT NULL,
199 "component_type" text NOT NULL,
200 CONSTRAINT "check_status" CHECK ("suggestions"."status" in ('pending', 'approved', 'rejected')),
201 CONSTRAINT "check_type" CHECK ("suggestions"."component_type" in
202 ('cpu', 'gpu', 'memory', 'storage', 'power_supply', 'motherboard', 'case', 'cooler', 'memory_card', 'optical_drive', 'sound_card', 'cables', 'network_adapter', 'network_card'))
203);
204--> statement-breakpoint
205CREATE TABLE "users" (
206 "id" serial PRIMARY KEY NOT NULL,
207 "username" text NOT NULL,
208 "password" text NOT NULL,
209 "email" text NOT NULL,
210 CONSTRAINT "users_username_unique" UNIQUE("username"),
211 CONSTRAINT "users_email_unique" UNIQUE("email")
212);
213--> statement-breakpoint
214ALTER TABLE "build_component" ADD CONSTRAINT "build_component_build_id_build_id_fk" FOREIGN KEY ("build_id") REFERENCES "public"."build"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
215ALTER TABLE "build_component" ADD CONSTRAINT "build_component_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
216ALTER TABLE "build" ADD CONSTRAINT "build_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
217ALTER TABLE "favorite_build" ADD CONSTRAINT "favorite_build_build_id_build_id_fk" FOREIGN KEY ("build_id") REFERENCES "public"."build"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
218ALTER TABLE "favorite_build" ADD CONSTRAINT "favorite_build_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
219ALTER TABLE "rating_build" ADD CONSTRAINT "rating_build_build_id_build_id_fk" FOREIGN KEY ("build_id") REFERENCES "public"."build"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
220ALTER TABLE "rating_build" ADD CONSTRAINT "rating_build_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
221ALTER TABLE "review" ADD CONSTRAINT "review_build_id_build_id_fk" FOREIGN KEY ("build_id") REFERENCES "public"."build"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
222ALTER TABLE "review" ADD CONSTRAINT "review_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
223ALTER TABLE "cpu" ADD CONSTRAINT "cpu_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
224ALTER TABLE "gpu" ADD CONSTRAINT "gpu_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
225ALTER TABLE "cables" ADD CONSTRAINT "cables_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
226ALTER TABLE "case_mobo_form_factors" ADD CONSTRAINT "case_mobo_form_factors_case_id_pc_case_component_id_fk" FOREIGN KEY ("case_id") REFERENCES "public"."pc_case"("component_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
227ALTER TABLE "case_ps_form_factors" ADD CONSTRAINT "case_ps_form_factors_case_id_pc_case_component_id_fk" FOREIGN KEY ("case_id") REFERENCES "public"."pc_case"("component_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
228ALTER TABLE "case_storage_form_factors" ADD CONSTRAINT "case_storage_form_factors_case_id_pc_case_component_id_fk" FOREIGN KEY ("case_id") REFERENCES "public"."pc_case"("component_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
229ALTER TABLE "cooler_cpu_sockets" ADD CONSTRAINT "cooler_cpu_sockets_cooler_id_cooler_component_id_fk" FOREIGN KEY ("cooler_id") REFERENCES "public"."cooler"("component_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
230ALTER TABLE "cooler" ADD CONSTRAINT "cooler_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
231ALTER TABLE "memory_card" ADD CONSTRAINT "memory_card_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
232ALTER TABLE "memory" ADD CONSTRAINT "memory_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
233ALTER TABLE "motherboard" ADD CONSTRAINT "motherboard_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
234ALTER TABLE "network_adapter" ADD CONSTRAINT "network_adapter_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
235ALTER TABLE "network_card" ADD CONSTRAINT "network_card_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
236ALTER TABLE "optical_drive" ADD CONSTRAINT "optical_drive_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
237ALTER TABLE "pc_case" ADD CONSTRAINT "pc_case_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
238ALTER TABLE "power_supply" ADD CONSTRAINT "power_supply_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
239ALTER TABLE "sound_card" ADD CONSTRAINT "sound_card_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
240ALTER TABLE "storage" ADD CONSTRAINT "storage_component_id_components_id_fk" FOREIGN KEY ("component_id") REFERENCES "public"."components"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
241ALTER TABLE "admins" ADD CONSTRAINT "admins_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
242ALTER TABLE "suggestions" ADD CONSTRAINT "suggestions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
243ALTER TABLE "suggestions" ADD CONSTRAINT "suggestions_admin_id_admins_user_id_fk" FOREIGN KEY ("admin_id") REFERENCES "public"."admins"("user_id") ON DELETE set null ON UPDATE cascade;
244
245CREATE OR REPLACE FUNCTION get_report_top_components()
246 RETURNS TABLE (
247 type TEXT,
248 brand TEXT,
249 name TEXT,
250 usage_count BIGINT,
251 avg_build_rating NUMERIC
252 )
253 LANGUAGE sql
254AS $$
255SELECT
256 c.type,
257 c.brand,
258 c.name,
259 COUNT(bc.component_id) AS usage_count,
260 AVG(rb.value) AS avg_build_rating
261FROM components c
262 JOIN build_component bc ON c.id = bc.component_id
263 JOIN build b ON bc.build_id = b.id
264 JOIN rating_build rb ON b.id = rb.build_id
265WHERE b.created_at >= CURRENT_DATE - INTERVAL '1 year'
266GROUP BY c.type, c.brand, c.name
267HAVING AVG(rb.value) >= 4.5
268ORDER BY usage_count DESC, avg_build_rating DESC
269LIMIT 15;
270$$;
271
272CREATE OR REPLACE FUNCTION get_report_user_reputation_leaderboard()
273 RETURNS TABLE (
274 username TEXT,
275 email TEXT,
276 approved_builds_count BIGINT,
277 total_favorites_received BIGINT,
278 avg_rating_received NUMERIC,
279 reputation_score NUMERIC
280 )
281 LANGUAGE sql
282AS $$
283WITH build_stats AS (
284 SELECT
285 b.id AS build_id,
286 b.user_id,
287 COUNT(DISTINCT fb.user_id) AS favorites_count,
288 AVG(rb.value) AS avg_rating
289 FROM build b
290 LEFT JOIN favorite_build fb ON b.id = fb.build_id
291 LEFT JOIN rating_build rb ON b.id = rb.build_id
292 WHERE b.is_approved = TRUE
293 GROUP BY b.id, b.user_id
294),
295 user_stats AS (
296 SELECT
297 user_id,
298 COUNT(build_id) AS approved_builds_count,
299 COALESCE(SUM(favorites_count), 0) AS total_favorites_received,
300 AVG(avg_rating) AS avg_rating_received
301 FROM build_stats
302 GROUP BY user_id
303 )
304SELECT
305 u.username,
306 u.email,
307 us.approved_builds_count,
308 us.total_favorites_received,
309 ROUND(CAST(COALESCE(us.avg_rating_received, 0) AS numeric), 2) AS avg_rating_received,
310 (
311 (us.approved_builds_count * 10) +
312 (us.total_favorites_received * 5) +
313 (COALESCE(us.avg_rating_received, 0) * 20)
314 ) AS reputation_score
315FROM user_stats us
316 JOIN users u ON u.id = us.user_id
317ORDER BY reputation_score DESC
318LIMIT 10;
319$$;
320
321CREATE OR REPLACE FUNCTION get_report_price_to_performance()
322 RETURNS TABLE (
323 build_name TEXT,
324 cpu_model TEXT,
325 gpu_model TEXT,
326 total_price NUMERIC,
327 performance_score NUMERIC,
328 price_to_performance_index NUMERIC
329 )
330 LANGUAGE sql
331AS $$
332WITH cpu_per_build AS (
333 SELECT
334 b.id AS build_id,
335 c.name AS cpu_model,
336 cpu.cores,
337 cpu.base_clock
338 FROM build b
339 JOIN build_component bc ON b.id = bc.build_id
340 JOIN components c ON bc.component_id = c.id
341 JOIN cpu ON c.id = cpu.component_id
342 WHERE LOWER(c.type) = LOWER('CPU')
343),
344 gpu_per_build AS (
345 SELECT
346 b.id AS build_id,
347 c.name AS gpu_model,
348 gpu.vram
349 FROM build b
350 JOIN build_component bc ON b.id = bc.build_id
351 JOIN components c ON bc.component_id = c.id
352 JOIN gpu ON c.id = gpu.component_id
353 WHERE LOWER(c.type) = LOWER('GPU')
354 )
355SELECT
356 b.name AS build_name,
357 cpu.cpu_model,
358 gpu.gpu_model,
359 b.total_price,
360 (cpu.cores * cpu.base_clock + gpu.vram * 100) AS performance_score,
361 ROUND(
362 CAST(
363 (cpu.cores * cpu.base_clock + gpu.vram * 100) / NULLIF(b.total_price, 0)
364 AS numeric),
365 4
366 ) AS price_to_performance_index
367FROM build b
368 JOIN cpu_per_build cpu ON b.id = cpu.build_id
369 JOIN gpu_per_build gpu ON b.id = gpu.build_id
370WHERE b.total_price > 0
371ORDER BY price_to_performance_index DESC
372LIMIT 20;
373$$;
374
375CREATE OR REPLACE FUNCTION get_report_budget_tier_popularity()
376 RETURNS TABLE (
377 price_tier TEXT,
378 builds_count BIGINT,
379 avg_favorites NUMERIC,
380 avg_rating NUMERIC,
381 unique_builders BIGINT,
382 engagement_score NUMERIC
383 )
384 LANGUAGE sql
385AS $$
386WITH price_tier_builds AS (
387 SELECT
388 b.id AS build_id,
389 b.user_id,
390 b.total_price,
391 CASE
392 WHEN b.total_price < 500 THEN 'Budget'
393 WHEN b.total_price < 1000 THEN 'Mid-Range'
394 WHEN b.total_price < 2000 THEN 'High-End'
395 ELSE 'Enthusiast'
396 END AS price_tier
397 FROM build b
398 WHERE b.is_approved = TRUE
399 AND b.created_at >= CURRENT_DATE - INTERVAL '6 months'
400),
401 favorites AS (
402 SELECT
403 build_id,
404 COUNT(DISTINCT user_id) AS favorites_count
405 FROM favorite_build
406 GROUP BY build_id
407 ),
408 engagement_stats AS (
409 SELECT
410 ptb.price_tier,
411 COUNT(DISTINCT ptb.build_id) AS builds_count,
412 AVG(COALESCE(f.favorites_count, 0)) AS avg_favorites,
413 AVG(rb.value) AS avg_rating,
414 COUNT(DISTINCT ptb.user_id) AS unique_builders
415 FROM price_tier_builds ptb
416 LEFT JOIN rating_build rb ON ptb.build_id = rb.build_id
417 LEFT JOIN favorites f ON ptb.build_id = f.build_id
418 GROUP BY ptb.price_tier
419 )
420SELECT
421 price_tier,
422 builds_count,
423 ROUND(CAST(avg_favorites AS numeric), 1) AS avg_favorites,
424 ROUND(CAST(COALESCE(avg_rating, 0) AS numeric), 2) AS avg_rating,
425 unique_builders,
426 ROUND(
427 CAST(
428 (builds_count * 2) +
429 (avg_favorites * 3) +
430 (COALESCE(avg_rating, 0) * 10) +
431 (unique_builders * 1.5)
432 AS numeric),
433 2
434 ) AS engagement_score
435FROM engagement_stats
436ORDER BY engagement_score DESC
437LIMIT 15;
438$$;
439
440CREATE OR REPLACE FUNCTION get_report_compatibility()
441 RETURNS TABLE (
442 cpu_combo TEXT,
443 motherboard_chipset TEXT,
444 total_builds BIGINT,
445 avg_satisfaction NUMERIC,
446 success_rate NUMERIC
447 )
448 LANGUAGE sql
449AS $$
450WITH cpu_mobo_pairs AS (
451 SELECT
452 cpu_comp.brand AS cpu_brand,
453 cpu_comp.name AS cpu_model,
454 mobo.chipset AS motherboard_chipset,
455 b.id AS build_id,
456 b.user_id,
457 b.created_at
458 FROM build b
459 JOIN build_component bc_cpu ON b.id = bc_cpu.build_id
460 JOIN components cpu_comp ON bc_cpu.component_id = cpu_comp.id
461 JOIN cpu ON cpu.component_id = cpu_comp.id
462 JOIN build_component bc_mobo ON b.id = bc_mobo.build_id
463 JOIN components mobo_comp ON bc_mobo.component_id = mobo_comp.id
464 JOIN motherboard mobo ON mobo.component_id = mobo_comp.id
465 WHERE b.is_approved = TRUE
466),
467 recent_activity AS (
468 SELECT DISTINCT build_id
469 FROM review
470 WHERE created_at >= CURRENT_DATE - INTERVAL '3 months'
471 ),
472 pair_metrics AS (
473 SELECT
474 cmp.cpu_brand,
475 cmp.cpu_model,
476 cmp.motherboard_chipset,
477 COUNT(DISTINCT cmp.build_id) AS total_builds,
478 AVG(COALESCE(rb.value, 0)) AS avg_satisfaction,
479 COUNT(DISTINCT ra.build_id) AS active_builds
480 FROM cpu_mobo_pairs cmp
481 LEFT JOIN rating_build rb ON cmp.build_id = rb.build_id
482 LEFT JOIN recent_activity ra ON cmp.build_id = ra.build_id
483 GROUP BY
484 cmp.cpu_brand,
485 cmp.cpu_model,
486 cmp.motherboard_chipset
487 HAVING COUNT(DISTINCT cmp.build_id) >= 2
488 )
489SELECT
490 CONCAT(cpu_brand, ' ', cpu_model) AS cpu_combo,
491 motherboard_chipset,
492 total_builds,
493 ROUND(CAST(avg_satisfaction AS numeric), 2) AS avg_satisfaction,
494 ROUND(
495 CAST(
496 (avg_satisfaction / 5.0) * 0.6 +
497 (CAST(active_builds AS DECIMAL) / total_builds) * 0.4
498 AS numeric),
499 3
500 ) AS success_rate
501FROM pair_metrics
502ORDER BY success_rate DESC, total_builds DESC
503LIMIT 15;
504$$;
505
506CREATE OR REPLACE FUNCTION get_report_storage_optimization()
507 RETURNS TABLE (
508 config_type TEXT,
509 ssd_brand TEXT,
510 builds_count BIGINT,
511 avg_storage_cost NUMERIC,
512 avg_total_capacity_gb NUMERIC,
513 avg_build_rating NUMERIC,
514 storage_cost_pct NUMERIC,
515 optimization_score NUMERIC
516 )
517 LANGUAGE sql
518AS $$
519WITH storage_configs AS (
520 SELECT
521 b.id AS build_id,
522 b.total_price,
523
524 ssd_comp.brand AS ssd_brand,
525 ssd_storage.capacity AS ssd_capacity,
526 ssd_comp.price AS ssd_price,
527
528 hdd_storage.capacity AS hdd_capacity,
529 hdd_comp.price AS hdd_price,
530
531 CASE
532 WHEN hdd_storage.capacity IS NULL THEN 'SSD-Only'
533 WHEN ssd_storage.capacity < 512 THEN 'SSD-Boot-HDD-Storage'
534 ELSE 'SSD-Primary-HDD-Archive'
535 END AS config_type
536 FROM build b
537 JOIN build_component bc_ssd ON b.id = bc_ssd.build_id
538 JOIN components ssd_comp ON bc_ssd.component_id = ssd_comp.id
539 JOIN storage ssd_storage ON ssd_storage.component_id = ssd_comp.id
540
541 LEFT JOIN build_component bc_hdd ON b.id = bc_hdd.build_id
542 LEFT JOIN components hdd_comp ON bc_hdd.component_id = hdd_comp.id
543 LEFT JOIN storage hdd_storage ON hdd_storage.component_id = hdd_comp.id
544
545 WHERE ssd_comp.type = 'storage'
546 AND b.is_approved = TRUE
547 AND b.created_at >= CURRENT_DATE - INTERVAL '1 year'
548
549 AND (
550 ssd_storage.type ILIKE '%nvme%'
551 OR ssd_storage.type ILIKE '%ssd%'
552 OR ssd_storage.type ILIKE '%m.2%'
553 OR ssd_storage.form_factor ILIKE '%m.2%'
554 )
555 AND (
556 hdd_storage.component_id IS NULL
557 OR hdd_storage.type ILIKE '%hdd%'
558 OR hdd_storage.form_factor ILIKE '%3.5%'
559 )
560),
561 config_performance AS (
562 SELECT
563 sc.config_type,
564 sc.ssd_brand,
565 COUNT(sc.build_id) AS builds_count,
566 AVG(sc.ssd_price + COALESCE(sc.hdd_price, 0)) AS avg_storage_cost,
567 AVG(sc.ssd_capacity + COALESCE(sc.hdd_capacity, 0)) AS avg_total_capacity,
568 AVG(rb.value) AS avg_build_rating,
569 AVG((sc.ssd_price + COALESCE(sc.hdd_price, 0)) / NULLIF(sc.total_price, 0)) AS storage_cost_ratio
570 FROM storage_configs sc
571 LEFT JOIN rating_build rb ON sc.build_id = rb.build_id
572 GROUP BY sc.config_type, sc.ssd_brand
573 HAVING COUNT(sc.build_id) >= 2
574 )
575SELECT
576 config_type,
577 ssd_brand,
578 builds_count,
579 ROUND(CAST(avg_storage_cost AS numeric), 2) AS avg_storage_cost,
580 ROUND(CAST(avg_total_capacity AS numeric), 0) AS avg_total_capacity_gb,
581 ROUND(CAST(COALESCE(avg_build_rating, 0) AS numeric), 2) AS avg_build_rating,
582 ROUND(CAST(COALESCE(storage_cost_ratio, 0) * 100 AS numeric), 1) AS storage_cost_pct,
583 ROUND(
584 CAST(
585 (COALESCE(avg_build_rating, 0) / 5.0 * 40) +
586 (avg_total_capacity / NULLIF(avg_storage_cost, 0) * 0.5) +
587 ((1 - COALESCE(storage_cost_ratio, 0)) * 30) +
588 (LN(CAST(builds_count + 1 AS numeric)) * 5)
589 AS numeric),
590 2
591 ) AS optimization_score
592FROM config_performance
593ORDER BY optimization_score DESC, builds_count DESC
594LIMIT 15;
595$$;
Note: See TracBrowser for help on using the repository browser.