Wyciągnięcie z bazy minimalnej liczby wierszej spełniających warunek

Wyciągnięcie z bazy minimalnej liczby wierszej spełniających warunek
DA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 27
0

Mam taki stan początkowy bazy danych:

Kopiuj
CREATE TABLE users (
  id INT,
  money decimal,
  priority int
);

INSERT INTO users (id, priority, money) VALUES (1, 7, 100);
INSERT INTO users (id, priority, money) VALUES (2, 2, 50);
INSERT INTO users (id, priority, money) VALUES (3, 3, 150);
INSERT INTO users (id, priority, money) VALUES (4, 1, 30);
INSERT INTO users (id, priority, money) VALUES (5, 8, 200);
INSERT INTO users (id, priority, money) VALUES (6, 8, 500);
INSERT INTO users (id, priority, money) VALUES (7, 4, 1200);

Powiedzmy, że potrzebuję uzyskać grupę użytkowników, których suma money wynosi >= 1400. Co więcej, chciałbym, by była to jak najmniejsza grupa, a w przypadku, gdy jest wiele tak samo liczebnych grup, to wybrać tą, w której suma priorytetów użytkowników jest największa.

Jak ktoś nie zrozumiał, to może tak: przychodzi opłacić rachunek. Trzeba wyciągnąć z bazy grupę ludzi, która jest w stanie go opłacić. Im mniej liczebna grupa tym lepiej. W przypadku, gdy jest kilka tak samo liczebnych grup, to zwracamy uwagę na priorytet.

Ma ktoś jakieś propozycje jak to zrobić? Ja wymyśliłem coś takiego:

Kopiuj
select
	(u1.priority + u2.priority + u3.priority) as total_priority,
    *
from users u1
cross join users u2
cross join users u3
where
	u1.id < u2.id
    and u2.id < u3.id
    and (u1.money + u2.money + u3.money) >= 1200
order by (u1.priority + u2.priority + u3.priority) desc

Ale to jest zapytanie dla konkretnie 3 użytkowników. Dla 2, czy 4 musiałbym dodać mniej/więcej joinów. Wolałbym takie ogólne zapytanie, dla dowolnej liczby użytkowników.

Demo: https://www.db-fiddle.com/f/5VeHEkTBAugcyY4xkWfu1U/1

M0
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 373
0

Takie coś jest Ok?

Kopiuj
WITH RECURSIVE user_combinations AS (
  SELECT
    ARRAY[id] AS user_ids,
    money,
    priority,
    1 AS num_users
  FROM users
  UNION ALL
  SELECT
    uc.user_ids || u.id,
    uc.money + u.money,
    uc.priority + u.priority,
    uc.num_users + 1
  FROM user_combinations uc
  JOIN users u ON u.id > ALL(SELECT unnest(uc.user_ids))
)
SELECT user_ids, money, priority
FROM user_combinations
WHERE money >= 1400
ORDER BY num_users ASC, priority DESC
LIMIT 1;

Edit: chociaż nie wiem jak z wydajnością tego

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.