не получая ожидаемого результата при присоединении - PullRequest
1 голос
/ 12 ноября 2011

я хочу отобразить #acc, у которого нет дочернего элемента, результатом должны быть B, C, D, E, но только B, C, D

create table #acc (mainid int,name nvarchar(20),subid int)

    insert into #acc values(1,'A',0)
    insert into #acc values(2,'B',1)
    insert into #acc values(3,'C',1)
    insert into #acc values(4,'D',1)
    insert into #acc values(5,'E',0)

    select  A.name from #acc
    A inner join #acc B
    on 
    A.subid   = B.mainid    

    drop table #acc 

Ответы [ 2 ]

1 голос
/ 12 ноября 2011

Прежде всего, я думаю, что вы должны переименовать столбец subid в superid или parentid или что-то в этом роде, потому что это B, C & D, которые sub -пункты A, а не наоборот.Возможно, непоследовательное именование является именно той причиной, по которой результаты вашего запроса кажутся вам непонятными, или вам трудно создать запрос, который возвращает правильные результаты.

Ваш запрос по существу возвращает элементы, которые являются некоторыми другимипредметы детей.Сами они могут иметь или не иметь своих детей.Например, если у B, C или D есть дети, ваш запрос вернет этих детей в дополнение к B, C и D.Это не совсем то, что вам нужно.

Здесь вам нужно не внутреннее соединение, а анти -соединение.Это когда результаты возвращаются на основании того факта, что что-то имеет не совпадение.Анти-объединения могут быть реализованы различными способами:

  1. Используя LEFT JOIN + IS NULL check:

    SELECT A.*
    FROM #acc A
      LEFT JOIN #acc B ON A.mainid = B.subid
    WHERE B.mainid IS NULL
    

    Здесь мы соединяем таблицу с самим собой ивозвращение левой стороны объединения, в которой правая сторона не имеет совпадений (т.е. возвращение строк со значениями mainid, которые никогда не встречаются в столбце subid).

  2. Использование NOT EXISTS:

    SELECT *
    FROM #acc A
    WHERE NOT EXISTS (
      SELECT *
      FROM #acc B
      WHERE A.mainid = B.subid
    )
    

    Этот запрос можно интерпретировать следующим образом: возвращать каждую строку из #acc, если не существует совпадения между mainid этой строки и subid любой другой строки.

  3. Использование NOT IN:

    SELECT *
    FROM #acc
    WHERE mainid NOT IN (
      SELECT subid
      FROM #acc
    )
    

    Это кажется мне наиболее простым (хотя и не обязательно наиболее эффективным): возвращать строки, в которых mainid отсутствует в спискевсе существующие subid значения.Если вы использовали NULL s вместо 0 в качестве значений subid корневых элементов, вам также придется изменить последний запрос, добавив этот фильтр в подзапрос:

    …
    WHERE subid IS NOT NULL
    

    В противном случаебудет работать неправильно.

Вы также можете прочитать эту тему:

0 голосов
/ 12 ноября 2011

Это сделает это

      select * from
        (select  A.mainid , A.name  from #acc
A left join #acc B
on A.subid   = B.mainid  ) as m where  m.mainid not in (select subid from #acc)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...