oracle sql по-разному выбирают / устанавливают ограничение по числу строк для разных групп в одном наборе данных - PullRequest
0 голосов
/ 17 апреля 2019

У меня в таблице есть 4 столбца: customer, product_id, Score, tag. В столбце тега 'new' и 'old' есть 2 значения.

, для каждого клиента есть оба product_id из 'new' и 'Старый тег (число варьируется) для каждого клиента, мы ранжируем product_id на основе оценки, а у тега у нас есть общее ограничение на количество продуктов для каждого клиента.он называется 'n_prod'

Я надеюсь выбрать (2/3 * n_prod) product_id из тега "old" и (1/3 * n_prod) продукт для тега "new" для каждого клиента, например, если нам нужновыберите 6 товаров, надеюсь, у меня будет 4 из «старого» тега (топ 4 по количеству баллов) и 2 из «нового» тега (топ 2 по баллам)

Я могу создать столбецвызываемый 'rn' использует следующую команду для ранжирования product_id на основе каждого клиента и тега

select customer, product_id, score, tag
      , row_number()over(partition by customer,tag, order by score desc) as rn 
from table

количество ограничений различно для разных групп: пробовал это, но не работает:

with tep as
(select customer, product_id, score, tag
      , row_number()over(partition by customer,tag, order by score desc) as rn 
from table)

select tep.*
from tep
where ( case 
         when tag='new' then rn<= round(n_prod*0.33,0)
         else then rn<= round(n_prod*0.66,0)
         end
);

Могу ли я объединить «где» с «случаем, когда» или «если еще»?

пересчитать ожидаемый результат: я надеюсь выбрать (2/3 * n_prod) product_id из тега «old» и (1/ 3 * n_prod) продукт для «нового» тега для каждого клиента, например, если нам нужно выбрать 6 продуктов, надеемся, что у нас будет 4 из «старого» тега (топ-4 по количеству баллов) и 2 из «нового» тега (2 лучших на основе оценки)

1 Ответ

2 голосов
/ 17 апреля 2019

Трудно быть уверенным без данных, но я думаю, что вам просто нужно использовать логическую логику в предложении where:

...
select tep.*
from tep
where (tag = 'new' and rn <= round(n_prod*0.33))
   or (tag = 'old' and rn <= round(n_prod*0.66));

Быстрая демонстрация с некоторыми подготовленными данными в другом CTE и n_prod в качестве переменной связывания:

var n_prod number;
exec :n_prod := 6;

with your_table (customer, product_id, score, tag) as (
            select 1234, 2345, level, 'old' from dual connect by level <= 10
  union all select 1234, 2345, level, 'new' from dual connect by level <= 10
),
tep as
(select customer, product_id, score, tag
      , row_number()over(partition by customer,tag order by score desc) as rn 
from your_table)
select tep.*
from tep
where (tag = 'new' and rn <= round(:n_prod*0.33))
or (tag = 'old' and rn <= round(:n_prod*0.66));

  CUSTOMER PRODUCT_ID      SCORE TAG         RN
---------- ---------- ---------- --- ----------
      1234       2345         10 new          1
      1234       2345          9 new          2
      1234       2345         10 old          1
      1234       2345          9 old          2
      1234       2345          8 old          3
      1234       2345          7 old          4

Кстати, вам, вероятно, необходимо увеличить количество цифр в множителях, которые вы используете для больших значений n_prod. При значениях 0,33 и 0,66 общее число возвращаемых строк начинает работать неправильно после ... er ... 28. (round(28*.33) равно 9; round(28*.66) равно 18; таким образом, общее число равно 27 вместо 28. При использовании 0,333 и 0,666 кажется безопасным до 253, с использованием 0,3333 и 0,6666 до 2503 и т. д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...