Dynamic Constraints

Intermediate
Scalar Subquery CASE Expression Dynamic Bounds

An inventory manager selects items for a display, but the rules come from a configuration table — the maximum number of items and the budget are stored externally rather than hard-coded. Additionally, category-specific rules apply: at least 2 items from category A and at most 3 from category B. This example shows how PackDB constraints can reference scalar subqueries (for dynamic bounds) and use CASE expressions (for category-level counting).

CREATE TABLE Config (id INTEGER, max_items INTEGER, budget INTEGER);
INSERT INTO Config VALUES (1, 5, 600);

CREATE TABLE Items (
    item_id INTEGER, name VARCHAR, category VARCHAR, value INTEGER
);
INSERT INTO Items VALUES
    (1, 'Premium Item A1', 'A', 150), (2, 'Premium Item A2', 'A', 140),
    (3, 'Premium Item A3', 'A', 100), (4, 'Standard Item B0', 'B', 130),
    (5, 'Standard Item B1', 'B', 120), (6, 'Standard Item B2', 'B', 110),
    (7, 'Standard Item B3', 'B', 90), (8, 'Basic Item C1', 'C', 80),
    (9, 'Basic Item C2', 'C', 70);
SELECT item_id, name, category, value, x as selected
FROM Items
DECIDE x IS BOOLEAN
SUCH THAT
    SUM(x) <= (SELECT max_items FROM Config WHERE id = 1) AND
    SUM(x * CASE WHEN category = 'A' THEN 1 ELSE 0 END) >= 2 AND
    SUM(x * CASE WHEN category = 'B' THEN 1 ELSE 0 END) <= 3 AND
    SUM(x * value) <= (SELECT budget FROM Config WHERE id = 1)
MAXIMIZE SUM(x * value);
1
SUM(x) <= (SELECT max_items FROM Config WHERE id = 1) — Total selected items cannot exceed the limit from the Config table (5 in this case).
2
SUM(x * CASE WHEN category = 'A' THEN 1 ELSE 0 END) >= 2 — At least 2 items from category A must be selected.
3
SUM(x * CASE WHEN category = 'B' THEN 1 ELSE 0 END) <= 3 — At most 3 items from category B.
4
SUM(x * value) <= (SELECT budget FROM Config WHERE id = 1) — Total value within budget (600).
5
MAXIMIZE SUM(x * value) — Maximize the total value of selected items.
item_id name category value selected
1Premium Item A1A1501
2Premium Item A2A1401
3Premium Item A3A1000
4Standard Item B0B1300
5Standard Item B1B1201
6Standard Item B2B1101
7Standard Item B3B900
8Basic Item C1C801
9Basic Item C2C700
The solver selects 5 items totaling exactly 600 (the budget limit): two from category A (Premium A1 at 150, Premium A2 at 140), two from category B (Standard B1 at 120, Standard B2 at 110), and one from category C (Basic C1 at 80). This satisfies the minimum 2 category-A items and stays within the maximum 3 category-B items. The key feature here is that the constraints reference the Config table dynamically — changing the budget or max_items in Config would change the optimal selection without modifying the query.
← Task Assignment Next: Portfolio Optimization →