Выберите строки с несколькими различными комбинациями значений столбцов

У меня есть таблица с 3 столбцами: id, val1 и val2.

Для каждого отдельного значения val2 я хочу выбрать все строки, для которых существует несколько различных значений val1.

Пример:

| id | val1 | val2 |
|------------------|
| 1  | A1   |  a2  |
| 2  | A1   |  a2  |
| 3  | A1   |  b2  |
| 4  | B1   |  b2  |
| 5  | A1   |  c2  |
| 6  | A1   |  c2  |
| 7  | A1   |  c2  |
| 8  | A1   |  d2  |
| 9  | C1   |  d2  |
| 10 | A1   |  d2  |

Желаемый результат:

| id | val1 | val2 |
|------------------|
| 3  | A1   |  b2  |
| 4  | B1   |  b2  |
| 8  | A1   |  d2  |
| 9  | C1   |  d2  |
| 10 | A1   |  d2  |

Мне не удалось придумать какой-либо запрос, который позволяет мне это сделать, может быть, у кого-то есть идея, как это решить.


person smerlin    schedule 25.05.2012    source источник
comment
Какая система БД? MSSQL 2005/08/12, MySQL...   -  person Paddy    schedule 25.05.2012
comment
Ряды 8 и 10 идентичны, за исключением идентификационного номера. Я не понимаю, почему вы включили 8 и 10, но исключили 1 и 2, которые также идентичны, за исключением идентификационного номера.   -  person Mike Sherrill 'Cat Recall'    schedule 25.05.2012
comment
@Catcall: существует только 1 отличное значение для val1 для val2=a2 (строка 1-2), но существует более 1 отдельного значения для val1 для val2=d2 (строка 8-10)   -  person smerlin    schedule 25.05.2012


Ответы (4)


Используя агрегированные оконные функции, вы также можете сделать это следующим образом:

SELECT
  id,
  val1,
  val2
FROM (
  SELECT
    *,
    MIN(val1) OVER (PARTITION BY val2) AS minval1,
    MAX(val1) OVER (PARTITION BY val2) AS maxval1
  FROM atable
) s
WHERE minval1 <> maxval1
person Andriy M    schedule 25.05.2012
comment
очень хорошо, ваш запрос почти в два раза быстрее для меня. и это более читабельно. - person smerlin; 25.05.2012

Вы можете использовать предложение having для поиска val2 с более чем одним различным значением val1. Например:

select  yt.*
from    YourTable yt
join    (
        select  val2
        from    YourTable
        group by
                val2
        having  count(distinct val1) > 1
        ) as filter
on      yt.val2 = filter.val2
person Andomar    schedule 25.05.2012
comment
@aF: это соответствует результатам примера, см. SQLFIddle Пэдди. - person Andomar; 25.05.2012

Попробуйте этот запрос:

SELECT * from tbl where val2 in (SELECT  val2 FROM `tbl`  group by val2 having  
 count(distinct(val1)) > 1)
person Er. Anurag Jain    schedule 25.05.2012

person    schedule
comment
@Romil: да, теперь это работает, так как ваши запросы и запросы Andomars верны, я проверю, что дает лучшую производительность с большей таблицей (однако моя таблица не такая большая) - person smerlin; 25.05.2012