Reputation: 315
I have the data as follows
|Fruit |Numbers|
|Apples | 50|
|Banana | 30|
|Oranges | 20|
|Grapes | 100|
|Peach | 30|
|Kiwi | 70|
I need to re-arrange them 3 bags in such a way that I have 3 bags of equal(or almost) number of fruits using NTILE. Could you please help?
Output should be like
|Bag_id|Contents |Count
|Bag 1 | Apples,Oranges,Peaches|100|
|Bag 2 | Kiwi,Banana |100|
|Bag 3 |Grapes|100|
Upvotes: 1
Views: 189
Reputation: 315
I had ~300 fruits, so based on @MatBailie, I found the soln.
Thank you all!!
SELECT Wm_concat(fruit),
bag
FROM (SELECT i.,
CASE
WHEN item <= 10 THEN item
ELSE 10 - item
END AS bag
FROM (SELECT b.,
Row_number()
OVER (
partition BY batch
ORDER BY cnt) AS item
FROM (SELECT t.*,
Ntile(50)
OVER (
ORDER BY cnt) AS batch
FROM tmp t) b) i)
GROUP BY bag;
Upvotes: 0
Reputation: 86765
SELECT
i.*,
CASE WHEN item <= 3 THEN item ELSE 7 - item END AS bag
FROM
(
SELECT
b.*,
ROW_NUMBER() OVER (PARTITION BY batch, ORDER BY numbers) AS item
FROM
(
SELECT
t.*,
NTILE(6) OVER (ORDER BY numbers) AS batch
FROM
your_table t
)
b
)
i
I'm on my phone, so I won't add the bit done by Gordon to concatenate the items in to a single row.
But this implements a Very simple bagging algorithm.
It happens to be Fairly good when you have 6 items to put in 3 bags.
It happens to be Awful when you have 4 items to put in 3 bags.
And it doesn't really cope with large amount of small numbers and a small amount of large numbers.
There are many algorithms for you to Google, and pick you preference.
But it's an example, using NTILE...
Upvotes: 1
Reputation: 1270443
If you just want two fruits in each basket (ignoring the numbers
column), then you can use ntile()
:
select 'Bag ' || tercile,
listagg(Fruit, ',') over (within group order by Fruit) as fruits
from (select t.*,
ntile(3) over (order by numbers) as tercile
from t
) t
group by tercile;
As with your sample results, the sum of numbers
is not even approximately equal across the baskets.
Upvotes: 0