W bazie danych przechowuję płatności. Każda płatność może być przypisana do jakiejś kategorii, jednak te przypisywanie ma być na podstawie reguł, np.:
- jeśli tytuł to pyszne.pl, to kategoria to jedzenie
- jeśli tytuł to enea, to kategoria to rachunki
Teraz chciałbym napisać takiego selecta, który zwróci mi płatności wraz z kategoriami przypisanymi na podstawie tychże reguł.
Baza wygląda tak:
Płatności:
create table payment
(
id int,
title text,
recipient text,
amount int,
category_id int null
);
Kategorie:
create table category
(
id int,
title text
);
Reguły:
create table assign_rule
(
id int,
description text
);
Przypisanie reguły do kategorii:
create table assign_rule_category
(
id int,
assign_rule_id int,
value text,
category_id int
);
Przypisywanie płatności do kategorii ogarnąłem na zasadzie takiej, że najpierw pobieram listę wszystkich płatności, potem listę wszystkich przypisań reguł do kategorii i łączę to w serwisie na zasadzie:
public int? GetCategory(PaymentEntity entity)
{
var rulesCategories = GetAllRulesCategories().Result;
foreach (var rule in rulesCategories)
{
switch ((Rule)rule.Rule_id)
{
case Rule.NAME_CONTAINS:
if (entityName.Contains(rule.Value))
return rule.Category_id;
break;
case Rule.TITLE_CONTAINS:
if (entityTitle.Contains(rule.Value))
return rule.Category_id;
break;
}
}
return null;
}
Zastanawiam się, czy jest możliwość ogarnięcia tego w 1 zapytaniu. Chciałbym, by dla tych danych wejściowych:
https://www.db-fiddle.com/f/puzvVCStRZX58G7Wbxj2Eu/0
wynik selecta wyglądał tak:
| id | title | recipient | amount | category_id |
|:--:|---------------------|------------------|-------:|:-----------:|
| 1 | internet bill | electric company | 100 | 3 |
| 2 | money | Mike | 200 | 2 |
| 3 | food ordered online | BestPizza | 80 | 1 |
Jak widać, przypisanie powinno być na podstawie tych reguł:
insert into assign_rule_category values
(1, 1, 'bill', 3), -- if 'title' contains 'bill', then assign payment to 'BILLS' category
(2, 1, 'food', 1), -- if 'title' contains 'food', then assign payment to 'FOOD' category
(3, 2, 'Mike', 2); -- if 'recipient' contains 'Mike', then assign payment to 'LOAN' category
Jakieś pomysły?