Refactor best production SQL query: Simplified and optimized the QUERY_GET_BEST_PRODUCTION by restructuring the query to use a WITH clause for better readability and performance. This change enhances the accuracy of production candidate selection by incorporating additional metrics and calculations.
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 1m33s

This commit is contained in:
Torsten Schulz (local)
2026-04-13 15:45:05 +02:00
parent 00ce7fc655
commit 3af0ab1156

View File

@@ -85,110 +85,36 @@ WHERE current_time BETWEEN '08:00:00' AND '17:00:00';
/// `worth_percent`: mit Fahrzeug `MAX` über Filialregionen; ohne Fahrzeug nur Direktor-Region.
/// **Ein** Spielercharakter je User (`ORDER BY id DESC LIMIT 1`, `health > 0`).
pub const QUERY_GET_BEST_PRODUCTION: &str = r#"
SELECT fdu.id falukant_user_id, CAST(fdu.money AS text) AS money, fdu.certificate, ftp.id product_id, ftp.label_tr,
COALESCE(ftp.category, 1)::int AS product_category, fdb.region_id,
(SELECT SUM(quantity) FROM falukant_data.stock fds WHERE fds.branch_id = fdb.id) AS stock_size,
WITH candidates AS (
SELECT
fdu.id AS falukant_user_id,
CAST(fdu.money AS text) AS money,
fdu.certificate,
ftp.id AS product_id,
ftp.label_tr,
COALESCE(ftp.category, 1)::int AS product_category,
fdb.region_id,
fdb.id AS branch_id,
COALESCE((SELECT SUM(quantity) FROM falukant_data.stock fds WHERE fds.branch_id = fdb.id), 0) AS stock_size,
COALESCE((SELECT SUM(COALESCE(fdi.quantity, 0)) FROM falukant_data.stock fds JOIN falukant_data.inventory fdi ON fdi.stock_id = fds.id WHERE fds.branch_id = fdb.id), 0) AS used_in_stock,
(
(
(
(
ftp.sell_cost
* (
COALESCE((SELECT COUNT(id) FROM falukant_data.production WHERE branch_id = fdb.id), 0) AS running_productions,
COALESCE((SELECT SUM(COALESCE(fdp.quantity, 0)) FROM falukant_data.production fdp WHERE fdp.branch_id = fdb.id), 0) AS running_productions_quantity,
ftp.sell_cost::float8 AS sell_cost,
CASE
WHEN EXISTS (
SELECT 1 FROM falukant_data.vehicle v
WHERE v.falukant_user_id = fdu.id
)
WHEN EXISTS (SELECT 1 FROM falukant_data.vehicle v WHERE v.falukant_user_id = fdu.id)
THEN bw.max_worth_pct
ELSE COALESCE(fdtpw_local.worth_percent::float8, 0.0)
END
) / 100.0
) * (
0.6 + 0.4 * (
LEAST(
100.0,
GREATEST(
0.0,
(2.0 * COALESCE(fdk_character.knowledge, 0)::float8
+ COALESCE(fdk_director.knowledge, 0)::float8) / 3.0
)
) / 100.0
)
)
)
- (
GREATEST(
END AS market_percent,
LEAST(100.0, GREATEST(0.0, (2.0 * COALESCE(fdk_character.knowledge, 0)::float8 + COALESCE(fdk_director.knowledge, 0)::float8) / 3.0)) AS quality_estimate,
(
(
(
(
ftp.sell_cost
* (
CASE
WHEN EXISTS (
SELECT 1 FROM falukant_data.vehicle v
WHERE v.falukant_user_id = fdu.id
)
THEN bw.max_worth_pct
ELSE COALESCE(fdtpw_local.worth_percent::float8, 0.0)
END
) / 100.0
) * (
0.6 + 0.4 * (
LEAST(
100.0,
GREATEST(
0.0,
(2.0 * COALESCE(fdk_character.knowledge, 0)::float8
+ COALESCE(fdk_director.knowledge, 0)::float8) / 3.0
)
) / 100.0
)
)
)
- (
(
6.0 + GREATEST(COALESCE(ftp.category, 1)::float8, 1.0)
) * (
1.0 - LEAST(
GREATEST(
COALESCE(fdu.certificate, 1)::float8
- GREATEST(COALESCE(ftp.category, 1)::float8, 1.0),
0.0
) * 0.035,
0.14
)
)
)
),
0.0
) * (COALESCE($3::float8, 0.0) / 100.0)
)
+ (
(
6.0 + GREATEST(COALESCE(ftp.category, 1)::float8, 1.0)
) * (
1.0 - LEAST(
GREATEST(
COALESCE(fdu.certificate, 1)::float8
- GREATEST(COALESCE(ftp.category, 1)::float8, 1.0),
0.0
) * 0.035,
0.14
)
)
)
)
) / NULLIF(ftp.production_time::float8, 0.0)
) AS worth,
fdb.id AS branch_id, (SELECT COUNT(id) FROM falukant_data.production WHERE branch_id = fdb.id) AS running_productions,
COALESCE((SELECT SUM(COALESCE(fdp.quantity, 0)) quantity FROM falukant_data.production fdp WHERE fdp.branch_id = fdb.id), 0) AS running_productions_quantity
(6.0 + GREATEST(COALESCE(ftp.category, 1)::float8, 1.0))
* (1.0 - LEAST(GREATEST(COALESCE(fdu.certificate, 1)::float8 - GREATEST(COALESCE(ftp.category, 1)::float8, 1.0), 0.0) * 0.035, 0.14))
) AS one_piece_cost,
COALESCE(ftp.production_time::float8, 0.0) AS production_time
FROM falukant_data.director fdd
JOIN falukant_data.character fdc ON fdc.id = fdd.director_character_id
JOIN falukant_data.falukant_user fdu ON fdd.employer_user_id = fdu.id
JOIN falukant_data.character user_character
ON user_character.id = (
JOIN falukant_data.character user_character ON user_character.id = (
SELECT c2.id
FROM falukant_data.character c2
WHERE c2.user_id = fdu.id
@@ -198,8 +124,7 @@ JOIN falukant_data.character user_character
)
JOIN falukant_data.branch fdb ON fdb.falukant_user_id = fdu.id AND fdb.region_id = fdc.region_id
JOIN (
SELECT tpw.product_id,
MAX(tpw.worth_percent)::float8 AS max_worth_pct
SELECT tpw.product_id, MAX(tpw.worth_percent)::float8 AS max_worth_pct
FROM falukant_data.town_product_worth tpw
WHERE tpw.region_id IN (
SELECT DISTINCT br.region_id
@@ -209,12 +134,34 @@ JOIN (
GROUP BY tpw.product_id
) bw ON TRUE
JOIN falukant_type.product ftp ON ftp.id = bw.product_id AND ftp.category <= fdu.certificate
LEFT JOIN falukant_data.town_product_worth fdtpw_local
ON fdtpw_local.region_id = fdb.region_id
AND fdtpw_local.product_id = ftp.id
LEFT JOIN falukant_data.town_product_worth fdtpw_local ON fdtpw_local.region_id = fdb.region_id AND fdtpw_local.product_id = ftp.id
JOIN falukant_data.knowledge fdk_character ON fdk_character.product_id = ftp.id AND fdk_character.character_id = user_character.id
JOIN falukant_data.knowledge fdk_director ON fdk_director.product_id = ftp.id AND fdk_director.character_id = fdd.director_character_id
WHERE fdd.id = $1 AND fdb.id = $2 ORDER BY worth DESC LIMIT 1;
WHERE fdd.id = $1 AND fdb.id = $2
)
SELECT
falukant_user_id,
money,
certificate,
product_id,
label_tr,
product_category,
region_id,
stock_size,
used_in_stock,
(
(
(sell_cost * market_percent / 100.0 * (0.6 + 0.4 * (quality_estimate / 100.0)))
- (GREATEST((sell_cost * market_percent / 100.0 * (0.6 + 0.4 * (quality_estimate / 100.0)) - one_piece_cost), 0.0) * (COALESCE($3::float8, 0.0) / 100.0))
- one_piece_cost
) / NULLIF(production_time, 0.0)
) AS worth,
branch_id,
running_productions,
running_productions_quantity
FROM candidates
ORDER BY worth DESC
LIMIT 1;
"#;
/// Debug-Variante zur Nachvollziehbarkeit der Direktoren-Entscheidung.
@@ -1917,11 +1864,13 @@ pub const QUERY_DEBTORS_SUBTRACT_REPUTATION: &str = r#"
"#;
pub const QUERY_DEBTORS_MARRIAGE_SATISFACTION_SUB: &str = r#"
UPDATE falukant_data.relationship r
SET marriage_satisfaction = GREATEST(0, COALESCE(r.marriage_satisfaction, 55) - $2::int),
UPDATE falukant_data.relationship_state rs
SET marriage_satisfaction = GREATEST(0, COALESCE(rs.marriage_satisfaction, 55) - $2::int),
updated_at = NOW()
FROM falukant_type.relationship rt
FROM falukant_data.relationship r
JOIN falukant_type.relationship rt ON rt.id = r.relationship_type_id
WHERE rt.id = r.relationship_type_id
AND rs.relationship_id = r.id
AND rt.tr IN ('married', 'engaged', 'wooing')
AND (r.character1_id = $1::int OR r.character2_id = $1::int);
"#;
@@ -1959,11 +1908,13 @@ pub const QUERY_DEBTORS_IMPRISONED_PENALTY_PLUS1: &str = r#"
"#;
pub const QUERY_DEBTORS_IMPRISONED_MARRIAGE_SUB1: &str = r#"
UPDATE falukant_data.relationship r
SET marriage_satisfaction = GREATEST(0, COALESCE(r.marriage_satisfaction, 55) - 1),
UPDATE falukant_data.relationship_state rs
SET marriage_satisfaction = GREATEST(0, COALESCE(rs.marriage_satisfaction, 55) - 1),
updated_at = NOW()
FROM falukant_type.relationship rt
FROM falukant_data.relationship r
JOIN falukant_type.relationship rt ON rt.id = r.relationship_type_id
WHERE rt.id = r.relationship_type_id
AND rs.relationship_id = r.id
AND rt.tr IN ('married', 'engaged', 'wooing')
AND (r.character1_id = $1::int OR r.character2_id = $1::int);
"#;
@@ -3419,10 +3370,13 @@ pub const QUERY_UPDATE_USER_HOUSE_SERVANT_DAILY: &str = r#"
"#;
pub const QUERY_UPDATE_MARRIAGE_SATISFACTION_ADD_FOR_CHARACTER: &str = r#"
UPDATE falukant_data.relationship r
SET marriage_satisfaction = GREATEST(0, LEAST(100, marriage_satisfaction + $1::int))
FROM falukant_type.relationship rt
UPDATE falukant_data.relationship_state rs
SET marriage_satisfaction = GREATEST(0, LEAST(100, COALESCE(rs.marriage_satisfaction, 55) + $1::int)),
updated_at = NOW()
FROM falukant_data.relationship r
JOIN falukant_type.relationship rt ON rt.id = r.relationship_type_id
WHERE rt.id = r.relationship_type_id
AND rs.relationship_id = r.id
AND rt.tr IN ('married', 'engaged', 'wooing')
AND (r.character1_id = $2::int OR r.character2_id = $2::int);
"#;
@@ -3611,10 +3565,10 @@ pub const QUERY_GET_MARRIAGE_ROWS: &str = r#"
r.id AS marriage_id,
r.character1_id AS m1,
r.character2_id AS m2,
r.marriage_satisfaction,
COALESCE(r.marriage_public_stability, 55)::int AS marriage_public_stability,
r.marriage_drift_high,
r.marriage_drift_low,
COALESCE((to_jsonb(rs)->>'marriage_satisfaction')::int, 55)::int AS marriage_satisfaction,
COALESCE((to_jsonb(rs)->>'marriage_public_stability')::int, 55)::int AS marriage_public_stability,
COALESCE((to_jsonb(rs)->>'marriage_drift_high')::int, 0)::int AS marriage_drift_high,
COALESCE((to_jsonb(rs)->>'marriage_drift_low')::int, 0)::int AS marriage_drift_low,
COALESCE(t1.tr, '') AS title1_tr,
COALESCE(t2.tr, '') AS title2_tr,
fu1.id AS user1_id,
@@ -3642,6 +3596,7 @@ pub const QUERY_GET_MARRIAGE_ROWS: &str = r#"
FROM falukant_data.relationship r
JOIN falukant_type.relationship rt ON rt.id = r.relationship_type_id
AND rt.tr IN ('married', 'engaged', 'wooing')
LEFT JOIN falukant_data.relationship_state rs ON rs.relationship_id = r.id
JOIN falukant_data.character c1 ON c1.id = r.character1_id
JOIN falukant_data.character c2 ON c2.id = r.character2_id
LEFT JOIN falukant_type.title t1 ON t1.id = c1.title_of_nobility
@@ -3652,25 +3607,24 @@ pub const QUERY_GET_MARRIAGE_ROWS: &str = r#"
#[allow(dead_code)] // Einfaches Update ohne Buff-Spalten; Daemon nutzt QUERY_UPDATE_MARRIAGE_STATE_AND_BUFFS.
pub const QUERY_UPDATE_MARRIAGE_STATE: &str = r#"
UPDATE falukant_data.relationship
UPDATE falukant_data.relationship_state
SET marriage_satisfaction = $1::smallint,
marriage_drift_high = $2::smallint,
marriage_drift_low = $3::smallint
WHERE id = $4::int;
marriage_drift_low = $3::smallint,
updated_at = NOW()
WHERE relationship_id = $4::int;
"#;
/// Inkl. Geschenk-/Fest-/Haus-Zähler (Migration `003_falukant_family_marriage_buffs.sql`).
/// `marriage_public_stability`: Migration `005_falukant_marriage_housepeace.sql`.
pub const QUERY_UPDATE_MARRIAGE_STATE_AND_BUFFS: &str = r#"
UPDATE falukant_data.relationship
UPDATE falukant_data.relationship_state
SET marriage_satisfaction = $1::smallint,
marriage_drift_high = $2::smallint,
marriage_drift_low = $3::smallint,
marriage_gift_buff_days_remaining = $4::smallint,
marriage_pending_feast_bonus = $5::smallint,
marriage_no_lover_bonus_counter = $6::smallint,
marriage_public_stability = $7::smallint
WHERE id = $8::int;
marriage_public_stability = $7::smallint,
updated_at = NOW()
WHERE relationship_id = $8::int;
"#;
/// Persistiert berechneten Hausfrieden (0..100), Migration `005_falukant_marriage_housepeace.sql`.
@@ -3713,12 +3667,15 @@ pub const QUERY_GET_USER_HOUSE_ROW_BY_USER: &str = r#"
"#;
pub const QUERY_MARRIAGE_SUBTRACT_SATISFACTION: &str = r#"
UPDATE falukant_data.relationship r
SET marriage_satisfaction = GREATEST(0, r.marriage_satisfaction - $2::int)
FROM falukant_type.relationship rt
UPDATE falukant_data.relationship_state rs
SET marriage_satisfaction = GREATEST(0, COALESCE(rs.marriage_satisfaction, 55) - $2::int),
updated_at = NOW()
FROM falukant_data.relationship r
JOIN falukant_type.relationship rt ON rt.id = r.relationship_type_id
WHERE rt.id = r.relationship_type_id
AND rs.relationship_id = r.id
AND rt.tr IN ('married', 'engaged', 'wooing')
AND r.id = $1::int;
AND rs.relationship_id = $1::int;
"#;
pub const QUERY_RESET_LOVER_UNDERPAY_COUNTERS: &str = r#"
@@ -3871,10 +3828,13 @@ pub const QUERY_GET_LOVER_PREGNANCY_CANDIDATES: &str = r#"
"#;
pub const QUERY_LOVER_BIRTH_PENALTY_MARRIAGE: &str = r#"
UPDATE falukant_data.relationship r
SET marriage_satisfaction = GREATEST(0, r.marriage_satisfaction - 8)
FROM falukant_type.relationship rt
UPDATE falukant_data.relationship_state rs
SET marriage_satisfaction = GREATEST(0, COALESCE(rs.marriage_satisfaction, 55) - 8),
updated_at = NOW()
FROM falukant_data.relationship r
JOIN falukant_type.relationship rt ON rt.id = r.relationship_type_id
WHERE rt.id = r.relationship_type_id
AND rs.relationship_id = r.id
AND rt.tr IN ('married', 'engaged', 'wooing')
AND (r.character1_id = $1::int OR r.character2_id = $1::int);
"#;