2016-02-11 6 views
2

У меня трудности с переносом головы вокруг этого запроса.Найти родителей, где все дети имеют одинаковое значение

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

company 
    id int IDENTITY, 
    name nvarchar(255) 

location 
    id int IDENTITY, 
    name nvarchar(255), 
    company int 

address 
    id int IDENTITY, 
    name nvarchar(255), 
    location int 

Пожалуйста, игнорирующие ключи и индексы для этого USECASE.

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

Пример работая данные:

select c.name, l.name, a.name 
from company as c 
join location as l on l.company = c.id 
left join address as a on a.location = l.id 



company  location   address 
---------- ---------------- ----------------- 
3-DOM  Ankh-Morpork  Street 1 
Adrenalize Cabot Cove  Avenue 2 
Adrenalize Mayberry   Road 49 
InterBlurb Hogsmeade   NULL 
InterBlurb Kakariko Village Alleyway 13 
Octocore Nibelheim   Blueberry Creek 2 
Octocore Mos Eisley  Blueberry Creek 2 

Пример результата:

company 
---------- 
3-DOM  
Octocore 

Как бы идти о достижении этого результата? Я пробовал группировать по l.company и подбираю count(distinct a.name) и прочее, но, похоже, я не могу его повесить. Объяснение с вашим запросом было бы весьма полезным, мне нужно это понять.

+1

Мне не ясно, где здесь определяются отношения родитель-ребенок. Почему «Adrenalize» исключается из вашего желаемого набора результатов? –

+0

См. Параграф выше приведенных рабочих данных: «и этот адрес будет одинаковым во всех местах под этой компанией». Места под названием «Адренализировать» имеют разные адреса, поэтому компания должна быть исключена. – krystah

ответ

1

Вы можете попробовать группировать по имени компании и сохранения только тех компаний, чьи адреса одинаковы во всех местах (это то, что делает внутренний запрос):

WITH the_cte (companyName, locationName, address) 
AS 
(
    SELECT c.name, l.name, a.name 
    FROM company AS c 
    INNER JOIN location AS l 
     ON l.company = c.id 
    LEFT JOIN address AS a 
     ON a.location = l.id 
) 

SELECT companyName, locationName, address 
FROM the_cte 
INNER JOIN 
(
    SELECT companyName, COUNT(DISTINCT CASE WHEN address IS NULL THEN 0 ELSE 1 END) 
    FROM the_cte 
    GROUP BY companyName 
    HAVING COUNT(DISTINCT CASE WHEN address IS NULL THEN 0 ELSE 1 END) = 1 
) t 
    ON the_cte.companyName = t.companyName 
+0

Не будет ли 'count' предложения having во внутреннем запросе выдавать' true', даже если некоторые имена адресов 'NULL'? – krystah

+0

Даже если мы использовали 'count (distinct (coalesce (a.name, ''))), я бы не знал, как узнать, соответствует ли счет 1, что все значения' ''' или адрес – krystah

+0

Используйте выражение 'CASE WHEN', чтобы присвоить' NULL' значение счётчика нулем. –

1
SELECT Name 
FROM (
       SELECT  company.name 
       FROM   company INNER JOIN 
             location ON company.id = location.company LEFT OUTER JOIN 
             address ON location.id = address.location 
       GROUP BY company.name 
       )sub 

WHERE Name NOT IN (
       SELECT  company.name 
       FROM   company INNER JOIN 
             location ON company.id = location.company LEFT OUTER JOIN 
             address ON location.id = address.location 
       WHERE  (address.location IS NULL) 
       GROUP BY company.name 

       UNION 

       SELECT  company.name 
       FROM   location INNER JOIN 
             address ON location.id = address.location INNER JOIN 
             company ON location.company = company.id 
       GROUP BY company.name 
       HAVING  (COUNT(DISTINCT address.name) >1) 

       ) 
  1. с внешним выберите запрос, мы объединим 3 sql-запроса
  2. Первый запрос получает все название компании
  3. второй запрос получает comapnies, у которого нет адресов
  4. Третий запрос получает компании, у которых более 1-го места
+1

Это хорошо работает –

+1

спасибо. я точно знаю. –

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