2016-07-11 1 views
2

Я пытаюсь получить список company_id, у которого нет заметок на уровне компании. Однако компания может иметь записи на уровне местоположения.MySQL Выберите раздел с левым соединением?

company 
------------------------- 
company_id name deleted 
1   Foo 0 
2   Bar 0 
3   Baz 0 

location 
----------------------- 
location_id company_id 
6   1 
7   2 
8   3 

note 
----------------------------------------- 
note_id company_id location_id deleted 
10  2   6   0   // location-level note 
11  1   7   0   // location-level note 
12  null  8   0   // location-level note 
13  2   null   0   // company-level note 

Я хочу, чтобы мой результат стол таким:

company_id name 
1   Foo 
3   Baz 

Update

Foo/company_id = 1 не имеет на уровне компании к сведению, потому что в записке также имеет location_id, что делает его записью на уровне местоположения. Примечания на уровне компании - это заметки, которые относятся только к компании (а не к местоположению).

Конец обновления

Я пытался сделать что-то вроде этого, но он возвращает пустой набор, так что я не уверен, если он работает и нет никаких компаний без нот на уровне компании или если я делаю что-то неправильно.

SELECT DISTINCT 
c.company_id, 
c.name 
FROM company AS c 
LEFT JOIN note AS n 
ON c.company_id = n.company_id 
WHERE 
c.deleted = 0 AND 
n.deleted = 0 AND 
n.location_id IS NOT NULL AND 
n.location_id != 0 AND 
c.company_id = (SELECT MAX(company_id) FROM company) 

Пересмотренный Принимается Ответа на этот вопрос Mike

SELECT 
    company_id, 
    name 
FROM company 
WHERE 
    deleted = 0 AND 
    company_id NOT IN (
     SELECT DISTINCT 
      c.company_id 
     FROM company AS c 
     INNER JOIN note AS n 
     ON c.company_id = n.company_id 
     WHERE (
      n.deleted = 0 AND 
       (n.location_id IS NULL OR 
       n.location_id = 0) 
     ) 
    ); 
+1

'Deleted' столбец отсутствует в выборочных данных, и эти условия' n.deleted = 0 И n.location_id IS NOT NULL И n.location_id! = 0' повернет 'Левый join' в' Внутренне join' –

+1

'c.company_id = (SELECT MAX (company_id) FROM company)' это будет гарантировать, что в результате будет только один вопрос 'company_id' –

+0

@Prdp, чтобы включить удаленные столбцы. Как я могу предотвратить превращение Left в Inner Join, а также поиск только заметок на уровне компании? – GreeKatrina

ответ

1

Самый простой способ думать об этом, чтобы сначала найти все компании, которые имеют компании заметки уровня, которые вы можете сделать с

select distinct c.company_id 
    from company c 
inner join notes n 
    on c.company_id = n.company_id 
    where n.location_id is null; 

После этого просто удалите эти компании из списка компании:

select company_id, 
     name 
    from company 
where company_id not in (select distinct c.company_id 
          from company c 
          inner join notes n 
           on c.company_id = n.company_id 
          where n.location_id is null); 

* Обновлено для использования внутреннего соединения вместо соединения, разделенного запятыми.

+1

Никогда не предлагайте 'разделенное запятой соединение ', когда кто-то уже использует явные' Joins' –

+0

Я не видел разделенное запятыми соединение раньше, можете ли вы, пожалуйста, обновить ответ, используя ключевые слова, как предлагалось @Prdp? – GreeKatrina

+0

Я только что добавил еще несколько предложений о вашем запросе, и он работает (обновленный вопрос). Спасибо! – GreeKatrina

0
SELECT DISTINCT c.* 
    FROM company c 
    LEFT 
    JOIN note n 
    ON n.company_id = c.company_id 
    AND n.location_id IS NULL 
WHERE n.note_id IS NULL;