2016-01-26 3 views
0

у меня основную таблицу со следующей структурой:Inner присоединиться, где не

id | created_at   | f1_id | f2_id 
1 2016-01-23 11:41:21 5  7 
2 2016-01-23 12:31:22 5  7 

Тогда у меня есть таблица 1: п к предыдущей таблице:

main_id | value 
1   aaa 
1   bbb 
2   ccc 

А потом у меня есть таблица 1: 1 к предыдущему с подтверждениями:

f1_id | f2_id | value | confirmed_at 
5  7  aaa  2016-01-25 21:41:51 
9  9  ccc  2016-01-25 23:51:45 

Теперь я хочу, чтобы получить все, не подтвержденные значения из диапазона дат от основной табл е. Как найти все недопустимые значения в диапазоне от основной таблицы?

f1 и f2 - 1: 1 таблицы, используемые в основной таблице, и подтвержденные значения.

SELECT * 
FROM maintable m 
INNER JOIN f1table f1 ON m.f1_id = f1.id 
INNER JOIN f2table f2 ON m.f2_id = f2.id 
INNER JOIN values v ON m.id = v.main_id 
INNER JOIN confirmed c ON (v.value = c.value AND c.f1_id = m.f1_id AND c.f2_id = m.f2_id) 
WHERE m.created_at BETWEEN '2016-01-20' AND '2016-01-24'; 

Этот SQL будет получать все подтвержденные значения ... но что относительно не подтверждено?

+0

Ваш вопрос непонятен. Что именно вы хотите в своем запросе? –

+0

Вы описываете 3 таблицы, но ваш примерный запрос содержит 5 таблиц: maintable, f1table, f2table, значения и подтвержденные.Пожалуйста, назовите таблицы по мере их описания, добавьте описания для отсутствующих таблиц и/или исправьте пример запроса, если необходимо. – Bampfer

ответ

1

Вы можете использовать шаблон anti-join. Используйте внешнее соединение для возврата всех строк из одной таблицы. Внешнее соединение будет возвращать совпадающие строки со второй таблицы, но также будет возвращать строки из первой таблицы, которые имеют , а не имеют соответствующую строку. Трюк - это предикат (условие) в предложении WHERE, который исключает строки, которые имели совпадение, оставляя только те строки, которые не имели соответствия.

На основании вашего запроса, чтобы вернуть все строки из m, v, f1 и f2 где нет соответствующей строки найдено в c, что-то вроде этого:

SELECT m.id 
    , m.created_at 
    , m.f1_id 
    , m.f2_id 
    , v.main_id 
    , v.value 
    FROM maintable m 
    JOIN f1table f1 ON m.f1_id = f1.id 
    JOIN f2table f2 ON m.f2_id = f2.id 
    JOIN values v ON m.id = v.main_id 

    LEFT 
    JOIN confirmed c 
    ON c.value = v.value 
    AND c.f1_id = m.f1_id 
    AND c.f2_id = m.f2_id 
WHERE c.f1_id IS NULL 

    AND m.created_at BETWEEN '2016-01-20' AND '2016-01-24' 

Любая строка из c, что " match "будет иметь значения, отличные от NULL, для столбцов, оцененных в условии соединения (то есть значение NULL в c.f1_id не будет удовлетворять сравнению сравнения равенства.) Таким образом, мы можем проверить значение, отличное от NULL, в этом столбце, чтобы определить, какие строки совпадают.


спецификация немного неоднозначным, о том, будет ли ожидать там быть строки из f1 и/или f2, когда соответствующая строка не существует в confirmed. Можно использовать внешнее объединение операций в таблицах f1 и f2 (добавить LEFT ключевое слово, прежде чем JOIN.)

против присоединиться к шаблону легче понять в менее сложном примере. Для возврата строки из a, для которого соответствующая строка не существует в b

SELECT a.foo 
    FROM a 
    LEFT 
    JOIN b 
    ON b.foo = a.foo 
WHERE b.foo IS NULL 
0

Попробуйте заменить внутреннее соединение к confirmed столу с NOT EXISTS где-п. Что-то вроде следующего:

SELECT * 
FROM maintable m 
INNER JOIN f1table f1 ON m.f1_id = f1.id 
INNER JOIN f2table f2 ON m.f2_id = f2.id 
INNER JOIN values v ON m.id = v.main_id 
WHERE m.created_at BETWEEN '2016-01-20' AND '2016-01-24' 
AND NOT EXISTS (SELECT * FROM confirmed c WHERE v.value = c.value AND c.f1_id = m.f1_id AND c.f2_id = m.f2_id) 
Смежные вопросы