Извлечение строк, которые имеют разные значения для столбца в ненормализованной таблице - PullRequest
1 голос
/ 08 января 2020

Принимая во внимание следующую таблицу фруктов, я хотел написать sql запрос, который возвращает фрукты, которые имеют оценку A и B. В этом примере ответ должен давать Orange и Lemon, поскольку они имеют оценки A и B. Apple & Pear, хотя они имеют рейтинг A и B, они не должны быть включены в результат, поскольку они не содержат оба. Один из способов go о - это использовать хранимую процедуру, но я хотел написать оператор sql, который можно расширить на любое количество оценок (не только A & B).

Fruit     Rating
Orange      A
Orange      B
Orange      C
Lemon       A
Lemon       B
Pear        B
Pear        C
Pear        C
Apple       A
Apple       C

Ожидаемый результат:

Fruit    Rating
Orange      A
Orange      B
Lemon       A
Lemon       B

Ответы [ 4 ]

2 голосов
/ 08 января 2020

Попробуйте этот подход:

WITH cte AS (
    SELECT Fruit
    FROM yourTable
    WHERE Rating IN ('A', 'B', 'C')
    GROUP BY Fruit
    HAVING COUNT(DISTINCT Rating) = 3
)

SELECT *
FROM yourTable
WHERE Fruit IN (SELECT Fruit FROM cte) AND Rating IN ('A', 'B', 'C');
1 голос
/ 08 января 2020

Вероятно, наиболее эффективным методом является использование exists:

select fr.*
from fruitrating fr
where (fr.rating = 'A' and
       exists (select 1 from fruitrating fr2 where fr2.fruit = fr.fruit and fr2.rating = 'B'
              )
      ) or
      (fr.rating = 'B' and
       exists (select 1 from fruitrating fr2 where fr2.fruit = fr.fruit and fr2.rating = 'A'
              )
      ) ;

Вы можете упростить эту логику c до:

select fr.*
from fruitrating fr
where (fr.rating in ('A', 'B') and
       exists (select 1 
               from fruitrating fr2
               where fr2.fruit = fr.fruit and
                     fr2.rating in ('A', 'B') and
                     fr2.rating <> fr.rating
              )
      ) ;

Однако это не обобщает так же просто для больших комбинаций.

Если вы просто хотели фрукты, а не ряды, то:

select fruit
from fruitrating
where rating in ('A', 'B')
group by fruit
having count(rating) = 2;

Используйте count(distinct rating), если в таблице могут быть дубликаты.

1 голос
/ 08 января 2020

Это работает в Oracle. Требуется поддержка DISTINCT в оконных функциях.

with data (Fruit,Rating) as (
  select 'Orange', 'A' from dual union all
  select 'Orange', 'B' from dual union all
  select 'Orange', 'C' from dual union all
  select 'Lemon', 'A' from dual union all
  select 'Lemon', 'B' from dual union all
  select 'Pear', 'B' from dual union all
  select 'Pear', 'C' from dual union all
  select 'Pear', 'C' from dual union all
  select 'Apple', 'A' from dual union all
  select 'Apple', 'C' from dual
)
select fruit, rating
from (
  select fruit, rating, cnt, max(cnt) over() max_cnt
  from (
    select fruit, rating,
      count(distinct rating) over(partition by fruit) cnt
    from data where rating in ('A','B')
  )
)
where cnt = max_cnt;
1 голос
/ 08 января 2020

Вот еще одно решение: я обновил свой ответ из-за этого комментария «Ваш запрос вернул бы фрукт, который имеет оценку А дважды» от Тима Бигелейзена. Спасибо!

select * 
from FTable
where fruit in (
select Fruit
   from FTable
   group by Fruit
   having sum(case when rating = 'A' then 1 else 0 end) = 1 
   and sum(case when rating = 'B' then 1 else 0 end) = 1)
and rating in ('A', 'B');

Вот это ДЕМО

РЕЗУЛЬТАТ:

  |  FRUIT  |  RATING  |
  +---------+----------+ 
  |  Orange |  A       |
  |  Orange |  B       |
  |  Lemon  |  A       |
  |  Lemon  |  B       |

И если вы хотите получить Фрукты, которые имеют более одного рейтинга A с рейтингом B и наоборот, используют это:

select * 
from FTable
where fruit in (
select Fruit
   from FTable
   group by Fruit
   having max(case when rating = 'A' then 'A' else '' end) = 'A' 
   and max(case when rating = 'B' then 'B' else '' end) = 'B')
and rating in ('A', 'B')
group by Fruit, rating;

А вот DEMO для этого

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