Получение только строк с лучшим рейтингом из подзапроса

#sql #plsql #rank

#sql #plsql #ранг

Вопрос:

Я хочу получить цену статьи для конкретного клиента.
Существует несколько уровней цен, которые я оценил в своем запросе.
Таким образом, статья A имеет цену за ранг 1, 4, 6. Результатом всегда должна быть цена с наименьшим рейтингом.

 Article B rank 3 ,5 
 

Таким образом, цена статьи A имеет рейтинг 1, а статья b — рейтинг 3.
Мой запрос приведен ниже.

 SELECT p2.* FROM(
SElect ART_ID, MIN(RANG) RANG FROM (
Select p.ART_ID, p.betrag ,
CASE p.PREIS_EBENE WHEN 'KA' THEN 1 WHEN 'KW' THEN 2 WHEN 'W' THEN 7 WHEN 'A' THEN 6 ELSE 99 END RANG
FROM MDART a
INNER JOIN MDPRSVK p ON (a.KLIENT_ID = p.KLIENT_ID AND a.ART_ID = p.ART_ID)
WHERE ICP_KZ.IS_SET(KENNUNG_USER, 'P') = 1
ORDER BY RANG)
GROUP BY ART_ID) T

INNER JOIN MDPRSVK p2 ON (p2.ART_ID = T.ART_ID AND p2.PREIS_EBENE = p.PREIS_EBENE)
 

я хочу, чтобы каждая статья появлялась в результате только один раз

Комментарии:

1. Похоже, ваш T подзапрос уже выполняет то, что вы хотите. Почему вы снова присоединяетесь к MDPRSVK? Пожалуйста, покажите пример данных и ожидаемый результат.

2. я получаю две строки, потому что мне также нужен «ПРЕДЛОГ» (по-немецки означает количество), поэтому, если я хочу предлог, мне нужно поместить его в группу by, и я получаю две строки: 32A00000426 840 6 32A00000426 841 1

3. Почему вы пометили свой запрос PL /SQL? Это язык программирования Oracle, в то время как вы ищете SQL-запрос. Вы используете Oracle? Или другую СУБД (MySQL, SQL Server, …)?

Ответ №1:

Вы пометили свой запрос PL / SQL, поэтому я предполагаю, что вашей СУБД может быть Oracle.

Если я правильно понимаю, таблица MDPRSVK содержит несколько цен за ART_ID. И вы хотите выбрать лучшую цену для каждого ART_ID (от наилучшего к худшему: ‘KA’ -> ‘KW’ -> ‘A’ -> ‘W’ -> любое другое PREIS_EBENE).

Для этого вы можете использовать оконную функцию ( ROW_NUMBER , RANK или DENSE_RANK ):

 select *
from mdprsvk
order by row_number() 
         over (partition by art_id 
               order by decode(preis_ebene, 'KA', 1, 'KW', 2, 'A', 3, 'W', 4, 5))
fetch first row with ties;
 

Это стандартный SQL. В Oracle FETCH FIRST доступно с версии 12c. В более ранних версиях вместо этого использовался подзапрос:

 select *
from
(
  select
    mdprsvk.*,
    row_number() over (partition by art_id 
                       order by decode(preis_ebene, 'KA', 1, 'KW', 2, 'A', 3, 'W', 4, 5))
      as rn
  from mdprsvk
)
where rn = 1;
 

Или используйте Oracle s KEEP FIRST `:

 select art_id, max(betrag)
               keep (dense_rank first
                     order by decode(preis_ebene, 'KA', 1, 'KW', 2, 'A', 3, 'W', 4, 5))
from mdprsvk
group by art_id;
 

Неясно, как вступает в игру MDART. Похоже, вы хотите ограничить свои результаты статьями для определенных клиентов, а KENNUNG_USER — это столбец в MDART для проверки. Если это так, добавьте WHERE предложение:

 where exists
(
  select *
  from mdart
  where mdart.klient_id = mdprsvk.klient_id
    and mdart.art_id = mdprsvk.art_id
    and icp_kz.is_set(mdart.kennung_user, 'p') = 1
)
 

Или с IN помощью вместо EXISTS :

 where (klient_id, art_id) in
(
  select klient_id, art_id
  from mdart
  where icp_kz.is_set(kennung_user, 'p') = 1
)
 

Комментарии:

1. большое вам спасибо. первый запрос — это именно то, что мне было нужно.