Найти наборы строк с несовпадающими значениями без большого самостоятельного объединения? - PullRequest
2 голосов
/ 24 ноября 2011

У меня есть такая таблица (базовый пример, а не реальная вещь):

FKEY  | NAME  | ATTRIBUTE_X
--------------------------
 1      '...'    42
 1      '...'    42
 1      '...'    42
 2      '...'    7
 2      '...'    7
 5      '...'    42
 5      '...'    42
 5      '...'    42
 5      '...'    42
 6      '...'    300
 6      '...'    300
 ....

Где - обычно - все значения attribute_x для данной клавиши одинаковы.(В моих реальных данных я вычисляю attribute_x из некоторых столбцов таблицы, и это свойство должно быть одинаковым для всех строк с одним и тем же fkey.

Теперь у меня есть несколько строк, в которых это свойство не хранится. Iхочу выполнить поиск по всей таблице, чтобы найти все FKEY с несоответствующими значениями attribute_x.

Пример:

--------------------------
 145678973      '...'    23
 145678973      '...'    22 // Error, should also be 23
 145678973      '...'    23

Мой наивный подход был:

SELECT distinct(TX1.FKEY)
FROM TABLEX TX1, TABLEX TX2
WHERE TX1.FKEY=TX2.FKEY
  AND TX1.ATTRIBUTE_X <> TX2.ATTRIBUTE_X
;

Но с моим реальнымданные, которые он не завершил (я запустил временное табличное пространство, и после того, как администратор баз данных увеличил временное табличное пространство до 20 гигабайт, запрос выполнялся в течение нескольких часов, а затем выручал).

В общем, есть ли более эффективныйзапрос для этого?


У меня есть решение с PL / SQL, где я просто циклически перебираю таблицу, отсортированную по FKEY, и если я нахожу другой attribute_x по сравнению с последней извлеченной записью, где клавиша остановилась,то же самое, я нашел ошибочную клавишу fkey.

Но это кажется таким уж примитивным :-) Есть ли эффективное решение для чистого SQL?

Ответы [ 5 ]

9 голосов
/ 24 ноября 2011

Самый простой способ:

select fkey
from tablex
group by fkey
having count(distinct attribute_x) > 1
4 голосов
/ 24 ноября 2011

Также должно работать следующее:

SELECT fkey FROM mytable GROUP BY fkey HAVING MIN(attribute_x) <> MAX(attribute_x)

4 голосов
/ 24 ноября 2011

Это должно сделать это

select
  FKEY
from
  (
  select distinct
    FKEY,
    ATTRIBUTE_X
  from
    MYTABLE
  )
group by
  FKEY
having
  count(*) > 1
2 голосов
/ 24 ноября 2011

попробуйте с этим

select count(*),FKEY from (Select distinct FKEY,ATTRIBUTE_X from TABLEX) 
having count(*)>1

РЕДАКТИРОВАТЬ Я исправил запрос там было 2 вместо 1

1 голос
/ 24 ноября 2011

Попробуйте это

SELECT * FROM tablex
WHERE (fkey, name, attribute_x) NOT IN
  (SELECT fkey, name, attribute_x FROM tablex
   GROUP BY fkey)

или (если имя не учитывается)

SELECT * FROM tablex
WHERE (fkey, attribute_x) NOT IN
  (SELECT fkey, attribute_x FROM tablex
   GROUP BY fkey)
...