SQL - установить разницу и получить поля, которые не являются частью разницы - PullRequest
1 голос
/ 05 мая 2011

У меня есть запрос, который в основном выполняет что-то вроде этого:

select a, b, c
from tab
where tab.state = 'A'
minus
select a, b, c
from tab
where tab.state = 'B'

В этом примере a, b и c являются ключевыми полями этой таблицы. state также является частью ключа, и я пытаюсь найти ситуации, когда существует запись в состоянии A, а не в состоянии B. Есть еще одно поле (не в ключе), о котором я хотел бы сообщить value, это может отличаться для одной и той же записи в разных штатах. Пример:

a  b  c  state  value
---------------------
1  1  1  A      12
1  2  2  A      1002
1  3  9  A      43
1  1  1  B      17.34
1  2  2  B      1002

В данном случае меня интересует строка, ключ которой равен 1,3,9, где состояние равно A. Я также хотел бы получить значение столбца value, но если я попытаюсь:

select a, b, c, value
from tab
where tab.state = 'A'
minus
select a, b, c, value
from tab
where tab.state = 'B'

То, что я вернул бы, это две строки:

a  b  c    value
----------------
1  1  1      12
1  3  9      43

По сути, я хочу иметь value в наборе результатов, но не участвовать в minus. Я чувствую, что упускаю что-то очевидное здесь, но, может быть, я слишком устала, чтобы это понять ...;)

Ответы [ 3 ]

3 голосов
/ 05 мая 2011

Очевидный способ сделать это так:

select a, b, c, value
from tab
where tab.state = 'A' and not exists (
  select 1                          -- let the optimizer do its thing
  from tab ti
  where tab.state = 'B' and ti.a=tab.a and ti.b=tab.b and ti.c=tab.c)

Я бы даже добавил distinct во внешний запрос, если данные могут иметь удвоенные значения.

1 голос
/ 05 мая 2011

Вы можете объединить все строки, где state = 'A', с соответствующими с помощью state = 'B' ...

SELECT t1.a, t1.b, t1.c, t1.value, t2.value v2
FROM (SELECT a, b, c, value FROM tab WHERE state = 'A') t1
     LEFT JOIN (SELECT a, b, c, value FROM tab WHERE state = 'B') t2
            ON t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c

... и затем выбрать строки, в которых не было совпадения:

 SELECT a, b, c, value
 FROM ( /* previous query */ )
 WHERE v2 IS NULL
0 голосов
/ 01 декабря 2013
SELECT a,
  b,
  c,
  value
FROM tab tab1
INNER JOIN
  (SELECT a, b, c FROM tab WHERE tab.state = 'A'
  MINUS
  SELECT a, b, c FROM tab WHERE tab.state = 'B'
  ) tab2
ON tab1.a  = tab2.a
AND tab1.b = tab2.b
AND tab1.c = tab2.c 

Я полагаю, что приведенный выше код поможет.

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