Changeset ff3a614
- Timestamp:
- 03/05/26 11:31:19 (4 months ago)
- Branches:
- main
- Parents:
- 41825d5
- Location:
- database
- Files:
-
- 3 edited
-
drizzle/util/reports.ts (modified) (1 diff)
-
drizzle/util/seed.ts (modified) (1 diff)
-
migrations/0000_colorful_scream.sql (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
database/drizzle/util/reports.ts
r41825d5 rff3a614 11 11 console.table(r1.rows); 12 12 13 const r2 = await db.execute(sql`SELECT * FROM get_report_user_ leaderboard()`);13 const r2 = await db.execute(sql`SELECT * FROM get_report_user_reputation_leaderboard()`); 14 14 console.log('--- User Reputation Leaderboard ---'); 15 15 console.table(r2.rows); 16 16 17 const r3 = await db.execute(sql`SELECT * FROM get_report_price_ performance()`);17 const r3 = await db.execute(sql`SELECT * FROM get_report_price_to_performance()`); 18 18 console.log('--- Price-to-Performance Analysis ---'); 19 19 console.table(r3.rows); 20 20 21 const r4 = await db.execute(sql`SELECT * FROM get_report_budget_tier ()`);21 const r4 = await db.execute(sql`SELECT * FROM get_report_budget_tier_popularity()`); 22 22 console.log('--- Budget Tier Popularity ---'); 23 23 console.table(r4.rows); -
database/drizzle/util/seed.ts
r41825d5 rff3a614 1 import "dotenv/config"; 1 2 import pg from 'pg'; 2 3 -
database/migrations/0000_colorful_scream.sql
r41825d5 rff3a614 242 242 ALTER 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 243 243 ALTER 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 245 CREATE 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 254 AS $$ 255 SELECT 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 261 FROM 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 265 WHERE b.created_at >= CURRENT_DATE - INTERVAL '1 year' 266 GROUP BY c.type, c.brand, c.name 267 HAVING AVG(rb.value) >= 4.5 268 ORDER BY usage_count DESC, avg_build_rating DESC 269 LIMIT 15; 270 $$; 271 272 CREATE 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 282 AS $$ 283 WITH 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 ) 304 SELECT 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 315 FROM user_stats us 316 JOIN users u ON u.id = us.user_id 317 ORDER BY reputation_score DESC 318 LIMIT 10; 319 $$; 320 321 CREATE 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 331 AS $$ 332 WITH 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 ) 355 SELECT 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 367 FROM 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 370 WHERE b.total_price > 0 371 ORDER BY price_to_performance_index DESC 372 LIMIT 20; 373 $$; 374 375 CREATE 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 385 AS $$ 386 WITH 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 ) 420 SELECT 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 435 FROM engagement_stats 436 ORDER BY engagement_score DESC 437 LIMIT 15; 438 $$; 439 440 CREATE 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 449 AS $$ 450 WITH 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 ) 489 SELECT 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 501 FROM pair_metrics 502 ORDER BY success_rate DESC, total_builds DESC 503 LIMIT 15; 504 $$; 505 506 CREATE 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 518 AS $$ 519 WITH 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 ) 575 SELECT 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 592 FROM config_performance 593 ORDER BY optimization_score DESC, builds_count DESC 594 LIMIT 15; 595 $$;
Note:
See TracChangeset
for help on using the changeset viewer.
