2016-02-24 2 views
0

Мне нужно получить строки из базы данных mysql следующим образом: у меня есть таблица контрактов, таблица позиций контракта и другая таблица, называемая udac. Мне нужны все контракты, у которых нет записи позиции с критериями, основанными на зависимости между контрактной позицией и udac. Если есть лучший способ сформулировать этот вопрос, дайте мне знать.выберите строки, где соответствующая запись не существует

Таблица Структуры

----contract---------------------  ---contractlineitem----------- 
| id | customer_id | entry_date |  | id | contract_id | udac_id | 
---------------------------------  ------------------------------ 
| 1 | 1234  | 2010-01-01 |  | 1 | 1   | 5  | 
| 2 | 2345  | 2016-01-31 |  | 2 | 1   | 2  | 
---------------------------------  | 3 | 1   | 1  | 
             | 4 | 2   | 4  | 
             | 5 | 2   | 2  | 
             ------------------------------ 

---udac---------- 
| id | udaccode | 
----------------- 
| 1 | SWBL/R | 
| 2 | SWBL | 
| 3 | ABL/R | 
| 4 | ABL  | 
| 5 | XRS/F | 
----------------- 

Учитывая приведенные выше данные, контракт 2 будет отображаться, но контракт 1 не будет, так как он имеет contractlineitems, которые указывают на udacs, которые заканчиваются на/F или/R.

Вот что у меня есть, но это неправильно.

SELECT c.* 
    FROM contract c 
    JOIN contractlineitem cli 
    ON c.id = cli.contract_id 
WHERE c.entry_timestamp > '2016-01-01 00:00:00' 
    AND NOT EXISTS (
      SELECT cli.id 
       FROM contractlineitem cli_i 
       JOIN udac u 
       ON cli_i.udac_id = u.id 
      WHERE u.udaccode LIKE '%/F' OR u.udaccode LIKE '%/R' 
       AND cli_i.contract_id = cli.contract_id); 
+0

Структуры таблиц, данные образца, ожидаемый результат ... http://stackoverflow.com/help/how-to-ask –

+0

@TomH Измененный вопрос. Это лучше? – lmerry213

+0

Вам нужно поместить круглые скобки вокруг вашей логики 'OR', иначе логика' AND' не будет вносить изменения. Порядок операций. –

ответ

0

Комментарий Тома, что ваше предложение WHERE является неправильным, может быть проблемой, которую вы преследуете. Кроме того, использование коррелированного подзапроса может быть проблематичным для производительности, если оптимизатор не может найти лучшего способа сделать это.

Вот лучший способ сделать это с помощью OUTER JOIN:

SELECT c.* 
    FROM contract c 
    JOIN contractlineitem cli 
    ON c.id = cli.contract_id 
    LEFT OUTER JOIN udac u 
    ON (u.id = cli.udac_id 
     AND (u.udaccode LIKE '%/F' OR u.udaccode LIKE '%/R')) 
WHERE c.entry_timestamp > '2016-01-01 00:00:00' 
    AND u.id IS NULL 

Попробуйте это и посмотреть, если он делает то, что вы хотите. Запрос по существу делает то, что вы заявили: он пытается присоединиться к udac, где код заканчивается на '/ F' или '/ R', но тогда он принимает только те, где он не может найти совпадение (u.id IS NULL).

Если одна и та же строка возвращена несколько раз неправильно, бросьте distinct спереди.

Смежные вопросы