SQL-запрос к двум таблицам - возвращает строки в одной таблице, в которых нет записей в другой - PullRequest
3 голосов
/ 11 апреля 2009

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

Категории: ID_Category, CategoryName

Суперкатегории: ID_SuperCategory, CategoryID, SuperCategoryID

Я помещаю отношения категории-подкатегории в таблицу SuperCategories. Я помещаю все категории в таблицу категорий.

Вот пример:

    Categories:
    ID_Category CategoryName
    1           Box
    2           Red Box
    3           Blue Box
    4           Blue Plastic Box
    5           Can
    6           Tin Can  
    
    SuperCategories:
    ID_Super CategoryID SuperCategoryID
    1        2          1
    2        3          1
    3        4          3
    4        6          5

CategoryID и SuperCategoryID относятся к первичному ключу ID_Category в таблице категорий.

Мне нужен запрос, который возвращает все имена категорий, которые не являются родителями других категорий:

Красная коробка
Синяя пластиковая коробка
Консервная банка

Это означает нахождение всех значений ID_Category, которые не отображаются в столбце SuperCategoryID (2, 4 и 6), но у меня возникают проблемы при написании SQL.

Я использую VB6 для запроса базы данных Access 2000.

Любая помощь приветствуется. Спасибо!

РЕДАКТИРОВАТЬ: Я проголосовал за каждый ответ, который дал мне что-то, что работает. Я принял ответ, который мне показался самым поучительным. Еще раз спасибо за вашу помощь!

Ответы [ 6 ]

6 голосов
/ 11 апреля 2009

Ответ Майка Пона работает, потому что он соединяет таблицу «Категории» с таблицей «Суперкатегории» как «СЛЕВАЯ ВНЕШНЕЕ СОЕДИНЕНИЕ» - это возьмет все записи из «Категории» и добавит столбцы из «Суперкатегории» к тем, где ссылка существует - там, где ее нет (например, там, где нет записи в «SuperCategories»), вы получите NULL для столбцов SuperCategories - и это именно то, что затем проверяет запрос Майка.

Если бы вы написали запрос так:

SELECT c.CategoryName, s.ID_Super 
FROM Categories c 
LEFT OUTER JOIN SuperCategories s ON c.ID_Category = s.SuperCategoryID

вы бы получили что-то вроде этого:

CategoryName    ID_Super
Box               1
Box               2
Red Box           NULL
Blue Box          3
Blue Plastic Box  NULL
Can               4
Tin Can           NULL

Таким образом, это в основном дает вам ваш ответ - все строки, в которых ID_Super в LEFT OUTER JOIN равен NULL, - это те, у которых нет записей в таблице SuperCategories. Все чисто? : -)

Марк

6 голосов
/ 11 апреля 2009
SELECT
     CAT.ID_Category,
     CAT.CategoryName
FROM
     Categories CAT
WHERE
     NOT EXISTS
     (
          SELECT
               *
          FROM
               SuperCategories SC
          WHERE
               SC.SuperCategoryID = CAT.ID_Category
     )

Или

SELECT
     CAT.ID_Category,
     CAT.CategoryName
FROM
     Categories CAT
LEFT OUTER JOIN SuperCategories SC ON
     SC.SuperCategoryID = CAT.ID_Category
WHERE
     SC.ID_Super IS NULL

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

5 голосов
/ 11 апреля 2009

включают только те категории, которые не являются суперкатегориями. Простое внешнее соединение

select CategoryName from Categories LEFT OUTER JOIN
SuperCategories ON Categories.ID_Category =SuperCategories.SuperCategoryID
WHERE SuperCategories.SuperCategoryID is  null
2 голосов
/ 11 апреля 2009

Не уверен, что синтаксис будет работать для Access, но что-то вроде этого будет работать:

select CategoryName from Categories
where ID_Category not in (
    select SuperCategoryID 
    from SuperCategories 
)
1 голос
/ 07 мая 2009

Я всегда придерживаюсь подхода внешнего соединения, как предлагает marc_s. При использовании ВНЕШНИХ СОЕДИНЕНИЙ много энергии. Часто мне приходится выполнять FULL OUTER JOIN для проверки данных по обеим сторонам запроса.

Вам также следует взглянуть на функцию ISNULL, если вы выполняете запрос, в котором данные могут находиться либо в таблице A, либо в таблице B, тогда я буду использовать функцию ISNULL для возврата значения из любого столбца.

Вот пример


 SELECT 
       isNull(a.[date_time],b.[date_time]) as [Time Stamp]
      ,isnull(a.[ip],b[ip]) as [Device Address]
      ,isnull(a.[total_messages],0) as [Local Messages]
      ,isnull(b.[total_messages],0) as [Remote Messages]
  FROM [Local_FW_Logs] a
FULL OUTER JOIN [Remote_FW_Logs] b 
on b.ip = a.ip
0 голосов
/ 30 мая 2013

У меня есть две таблицы interface_category и interface_subcategory.

Interface_subcategory содержит SubcategoryID, CategoryID, Name(SubcategoryName)

Interface_category содержит CategoryID, Name(CategoryName)

Теперь я хочу вывести CategoryID и Имя (имя подкатегории)

Запрос, который я написал ниже и его работа для меня

select ic.CategoryID, ic.Name CategoryName, ISC.SubCategoryID, ISC.Name SubCategoryName from Interface_Category IC
inner join Interface_SubCategory ISC
on ISC.CategoryID = ic.CategoryID
order by ic.CategoryID, isc.SubCategoryID
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...