PostgreSQL: сравнение двух наборов результатов не работает - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть таблица, которая содержит 3 столбца идентификаторов, clothes, shoes, customers и связывает их.

У меня есть запрос, который отлично работает:

select clothes, shoes from table where customers = 101 (вся одежда и обувь заказчика 101). Это возвращает

clothes - shoes (SET A)
1          6
1          2
33         12
24         null   

Другой запрос, который отлично работает:

select clothes ,shoes from table where customers in (select customers from table where clothes = 1 and customers <> 101 ) (вся одежда и обувь любого другого клиента, кроме 101, с указанной одеждой). Это возвращает

shoes - clothes(SET B)
6          null
null         24
1            1
2            1 
12          null
null         26
14           null

Теперь я хочу получить всю одежду и обувь из КОМПЛЕКТА А, которых нет в КОМПЛЕКТЕ В.

Итак (пример) select from SET A where NOT IN SET B. Это должно вернуть только одежду 33, верно?

Я пытаюсь преобразовать это в рабочий запрос:

select clothes, shoes from table where  customers = 101 
and
(clothes,shoes) not in 
 (   
   select clothes,shoes from
   table where customers in 
   (select  customers   from table where clothes = 1 and customers <> 101 ) 
 ) ;

Я пробовал разные синтаксисы, но выше выглядит больше логики.

Проблема в Я никогда не получаю одежду 33, только пустой набор.

Как мне это исправить? Что идет не так?

Спасибо

Редактировать, вот содержимое таблицы

id  shoes   customers   clothes
1    1      1           1
2    1      4           1
3    1      5           1
4    2      2           2
5    2      3           1
6    1      3           1
44   2      101         1
46   6      101         1
49   12     101         33
51   13     102 
52          101         24
59          107         51
60          107         24
62   23     108         51
63   23     108         2
93          124         25
95   6      125 
98          127         25
100  3      128 
103  24     131 
104  25     132 
105         102         28
106  10     102 
107  23     133 
108         4           26
109  6      4   
110         4           24
111  12     4   
112  14     4   
116         102         48
117         102         24
118         102         25
119         102         26
120         102         29
122         134         31

Ответы [ 2 ]

0 голосов
/ 18 ноября 2018

Для PostgreSQL null является неопределенным значением, поэтому вы должны избавиться от потенциальных нулей в своем результате:

select id,clothes,shoes from t1 where  customers = 101 -- or select id... 
and (
 clothes  not in 
 (   
   select COALESCE(clothes,-1) from
   t1 where customers in 
   (select  customers   from t1 where clothes = 1 and customers <> 101 ) 
 ) 
OR 
 shoes not in 
 (   
   select COALESCE(shoes,-1) from
   t1 where customers in 
   (select  customers   from t1 where clothes = 1 and customers <> 101 ) 
  )
 )

если бы вы хотели уникальные пары, вы бы использовали:

select clothes, shoes from t1 where  customers = 101 
and
(clothes,shoes)  not in 
 (   
   select coalesce(clothes,-1),coalesce(shoes,-1) from
   t1 where customers in 
   (select  customers   from t1 where clothes = 1 and customers <> 101 ) 
 ) ;

Вы не можете получить "одежду 33", если выбираете столбцы одежды и обуви ...

Также, если вам нужно точно знать, какая колонка, одежда или обувь были уникальны для этого клиента, вы можете использовать этот маленький «хак»:

select id,clothes,-1 AS shoes from t1 where  customers = 101 
and 
 clothes  not in 
 (   
   select COALESCE(clothes,-1) from
   t1 where customers in 
   (select  customers   from t1 where clothes = 1 and customers <> 101) 
 )  
 UNION
  select id,-1,shoes from t1 where  customers = 101 
   and 
   shoes not in 
   (   
    select COALESCE(shoes,-1) from
    t1 where customers in 
    (select  customers   from t1 where clothes = 1 and customers <> 101) 
   )

И ваш результат будет:

id=49, clothes=33, shoes=-1

(я предполагаю, что нет никакой одежды или обуви с идентификатором -1. Вы можете указать здесь любую экзотическую ценность)

Приветствия

0 голосов
/ 17 ноября 2018

Предложение except в PostgreSQL работает так же, как оператор minus в Oracle.Я думаю, что это даст вам то, что вы хотите.

Я думаю, что условно ваш запрос выглядит правильно, но я подозреваю, что эти противные нули влияют на ваши результаты.Точно так же, как нуль не-НЕ равен 5 (это ничто, поэтому он ни равен, ни не равен ничему), так и ноль также не-НЕ "во всем" ...

select clothes, shoes
from table1
where customers = 101

except  

select clothes, shoes
from table1
where customers in (
  select customers
  from table1
  where clothes = 1 and customers != 101
)
...