Соединения SQL с NOT IN отображают неверные данные - PullRequest
0 голосов
/ 22 сентября 2019

У меня есть 3 таблицы, как показано ниже, и мне нужны данные, где Expense.Expense_Code не должен быть доступен в Income.Income_Code.

Таблица: База

+----+-----------+----------------+
| ID | Reference | Reference_Name |
+----+-----------+----------------+
|  1 |     10000 | AAAA           |
|  2 |     10001 | BBBB           |
|  3 |     10002 | CCCC           |
+----+-----------+----------------+

Таблица: расходы

+-----+---------+--------------+----------------+
| EID | BASE_ID | Expense_Code | Expense_Amount |
+-----+---------+--------------+----------------+
|   1 |       1 | I0001        |             25 |
|   2 |       1 | I0002        |             50 |
|   3 |       2 | I0003        |             75 |
+-----+---------+--------------+----------------+

Таблица: доходы

+------+---------+-------------+------------+
| I_ID | BASE_ID | Income_Code | Income_Amt |
+------+---------+-------------+------------+
|    1 |       1 | I0001       |         10 |
|    2 |       1 | I0002       |         20 |
|    3 |       1 | I0003       |         30 |
+------+---------+-------------+------------+


SELECT  DISTINCT Base.Reference,Expense.Expense_Code
FROM Base 
JOIN Expense ON Base.ID = Expense.BASE_ID
JOIN Income ON Base.ID = Income.BASE_ID
WHERE Expense.Expense_Code IN ('I0001','I0002')
AND Income.Income _CODE NOT IN ('I0001','I0002')

Я ожидаю, что данные не будут восстановлены.

Однако я получаю результат, как показано ниже:

+-----------+--------------+
| REFERENCE | Expense_Code |
+-----------+--------------+
|     10000 | I0001        |
|     10000 | I0002        |
+-----------+--------------+

Для Base.Reference (10000), Expense.Expense_Code = 'I0001', 'I0002' тот же код расхода доступен в таблице доходов, поэтому я не должен получатьлюбые данные.

Я пытаюсь сделать что-то не так с соединениями.

Заранее спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 22 сентября 2019

... Мне нужны данные, где Expense.Expense_Code не должен быть доступен в Income.Income_Code

Следующий запрос будет получать эти данные:

select b.*, e.*
from base b
join expense e on e.base_id = b.id
left join income i on i.base_id = e.base_id
                  and e.expense_code = i.income_code
where i.i_id is null

Для справки: скрипт данных (слегка измененный):

create table base (
  id number(6),
  reference number(6),
  reference_name varchar2(10)
);

insert into base (id, reference, reference_name) values (1, 10000, 'AAAA');
insert into base (id, reference, reference_name) values (2, 10001, 'BBBB');
insert into base (id, reference, reference_name) values (3, 10002, 'CCCC');

create table expense (
  eid number(6),
  base_id number(6),
  expense_code varchar2(10),
  expense_amount number(6)
);

insert into expense (eid, base_id, expense_code, expense_amount) values (1, 1, 'I0001', 25);
insert into expense (eid, base_id, expense_code, expense_amount) values (2, 1, 'I0002', 50);
insert into expense (eid, base_id, expense_code, expense_amount) values (3, 1, 'I0003', 75);
insert into expense (eid, base_id, expense_code, expense_amount) values (4, 2, 'I0004', 101);

create table income (
  i_id number(6),
  base_id number(6),
  income_code varchar2(10),
  income_amt number(6)
);

insert into income (i_id, base_id, income_code, income_amt) values (1, 1, 'I0001', 10);
insert into income (i_id, base_id, income_code, income_amt) values (2, 1, 'I0002', 20);
insert into income (i_id, base_id, income_code, income_amt) values (3, 1, 'I0003', 30);

Результат:

ID  REFERENCE  REFERENCE_NAME  EID  BASE_ID  EXPENSE_CODE  EXPENSE_AMOUNT
--  ---------  --------------  ---  -------  ------------  --------------
2      10,001  BBBB              4        2  I0004                    101
0 голосов
/ 24 сентября 2019

Вы вообще не объединяете таблицы EXPENSE и INCOME в своем запросе.Должно быть условие, чтобы объединить эти таблицы, чтобы получить желаемый результат.Вы также можете использовать предложение NOT EXISTS.Предпочитайте использовать NOT EXISTS вместо NOT IN, так как он работает лучше в случае, если в столбцах, к которым вы присоединяетесь, допускаются значения NULL.

SELECT * FROM BASE B 
JOIN EXPENSE E ON B.ID=E.BASE_ID
WHERE E.EXPENSE_CODE NOT EXISTS (SELECT I.INCOME_CODE FROM INCOME I WHERE I.I_ID=E.EID)
0 голосов
/ 22 сентября 2019

Когда выполняется первое объединение, вы заканчиваете двумя строками с идентификатором 1, потому что отношения между таблицами не равны 1o1, следовательно, каждая строка первой таблицы будет присоединяться к ней по линии, идущей из второй таблицы.Например: Вывод первого оператора соединения

Затем, когда вторая часть вашего оператора выполняется, СУБД находит два идентификатора 1 из первой объединенной таблицы (BASE + EXPENSE) и3 из третьей таблицы (ДОХОД).

Опять же, поскольку между таблицами не существует отношения 1: 1, каждая строка из первой объединенной таблицы будет иметь соединенную строку из второй таблицы, например: Вывод второго оператора соединения

Наконец, когда он читает ваше предложение where и выводит то, что вы видите.Я выделил исключенные строки из предложения where Вывод инструкции where

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