I have the following problem:
Scenario:
I've recomposed the table structure to indicate the problem and to hide the irrelevant details.
Let's say I have a table of items.
Item: item_id | buyer_id | unit_id | status_id
All the columns have a not null value referencing to corresponding table.
Other table that I have is a price-catalog with the following structure:
Price: price_id | buyer_id | unit_id | status_id | price
Here any of the referencing values may have the value "-1" meaning "All". So we could have the following rows in price table:
| price_id | buyer_id | unit_id | status_id | price |
| 1 | -1 | 1 | 2 | 15 |
| 2 | 1 | 1 | 2 | 25 |
| 3 | -1 | -1 | 3 | 13 |
Here price 1 would match items with any buyer_id and unit_id = 1
, status_id = 2
and price 2 would math items with buyer_id = 1
, unit_id = 1
and status_id = 2
. Price 3 would match items with any buyer_id
, any unit_id
and status_id = 3
.
If there are multiple prices matching an item the selection is done with the following logic: Take the price that has the most fields specified (smallest amount of -1 values). If there are multiple prices with the same amount of -1 values then we pick the one that has a value different from -1 in the buyer_id
. If such doesn't exist we pick the one with "not -1" value at unit_id
and last the one with "not -1" value at status.
We can assume that there are not multiple prices matching the exact same group of prices (all prices have a unique combination of buyer_id
, unit_id
and status_id
.)
Problem:
Now I need to make query that selects the right price for each item in item-table. So far i got this:
SELECT item_id, price FROM item INNER JOIN price ON 1=1 AND (price.buyer_id = item.buyer_id OR price.buyer_id = -1) AND (price.unit_id = item.unit_id OR price.unit_id = -1) AND (price.status_id = item.status_id OR price.status_id = -1)
Basically this will get all the matching prices. So if we have item with buyer_id = 1
, unit_id = 1
and status_id = 2
we would get two rows:
| item_id | price | | 1 | 15 | | 1 | 25 |
My first idea was to use GROUP BY
, but I haven't figured out how to do it so that the price selected is the right one and not just a random/first(?) one.
EDIT: Tried to order the rows (ORDER BY buyer_id DESC, unit_id DESC, status_id DESC
) and then group the results based on the ordered sub-query but it seems that the order by doesn't work that way.
So how can I select the right row in GROUP BY
? Or what would be an alternative solution to get right prices with a single query (sub-queries are fine)?
Altering the table structure is not really an option in this particular case.
Update
I've been using the solution I submitted earlier but the amount of criteria that the price is selected by has gone up from three to five. This means that I currently have a list of 32 different combinations in my CASE WHEN
structure. In case I would need to add another one the list will double again, so I'm still looking for a better solution.