Как я могу вернуть строку, если ее идентификатор не найден в другой таблице? - PullRequest
10 голосов
/ 16 ноября 2010

У меня есть 2 таблицы в базе данных MS SQL 2008, листинги и ListingType, я хочу создать оператор выбора, который выдаст мне все строки из листинга, у которых нет ListingID в таблице ListingType.

Я очень озадачен тем, как вообще начать это утверждение.

Пример SQL-выражения - намного больше, чем я объяснил, но вы сможете получить то, что я от него запрашиваю.

SELECT     Listing.Title, Listing.MLS, COALESCE (Pictures.PictureTH, '../default_th.jpg') AS PictureTH, COALESCE (Pictures.Picture, '../default.jpg') AS Picture, Listing.ID, 
                      Listing.Description, Listing.Lot_Size, Listing.Building_Size, Listing.Bathrooms, Listing.Bedrooms, Listing.Address1, Listing.Address2, 
                      Listing.City, Locations.Abbrev, Listing.Zip_Code, Listing.Price, Listing.Year_Built, ListingTypeMatrix.ListingTypeID
FROM         Listing INNER JOIN
                      Locations ON Listing.State = Locations.LocationID LEFT OUTER JOIN
                      ListingTypeMatrix ON Listing.ID = ListingTypeMatrix.ListingID LEFT OUTER JOIN
                      Pictures ON Listing.ID = Pictures.ListingID
WHERE     (ListingTypeMatrix.ListingTypeID = '4') AND 
          ((Pictures.ID IS NULL) OR (Pictures.ID =
                          (SELECT     MIN(ID)
                            FROM          Pictures
                            WHERE      (ListingID = Listing.ID))))

ListingTypeMatrix.ListingTypeID = '4' - это часть, на которую я не знаю, на что ее изменить, потому что для нее не будет записи.

Ответы [ 5 ]

28 голосов
/ 16 ноября 2010

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

SELECT t.*
  FROM LISTING t
 WHERE NOT EXISTS(SELECT NULL
                    FROM LISTINGTYPE lt
                   WHERE lt.listingid = t.listingid)

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

SELECT t.*
  FROM LISTING t
 WHERE t.listingid NOT IN (SELECT lt.listingid
                             FROM LISTINGTYPE lt)

Использование LEFT JOIN / IS NULL

   SELECT t.*
     FROM LISTING t
LEFT JOIN LISTINGTYPE lt ON lt.listingid = t.listingid
    WHERE lt.listingid IS NULL

Сводка

Цитата :

В SQL Server предикаты NOT EXISTS и NOT IN являются наилучшим способом поиска пропущенных значений, если оба рассматриваемых столбца NOT NULL.Они производят безопасные эффективные планы с некоторым анти-объединением.

LEFT JOIN / IS NULL менее эффективен, так как не пытается пропустить уже соответствующие значения в правой таблице, возвращая все результаты и фильтруяих вместо

3 голосов
/ 16 ноября 2010

Следующий SQL вернет все записи Listing без соответствующей записи ListingType

SELECT *
FROM Listing
LEFT JOIN ListingType ON Listing.ID = ListingType.ListingID
WHERE ListingType.ID IS NULL
3 голосов
/ 16 ноября 2010
   SELECT *
     FROM Listing l
LEFT JOIN ListingType t ON l.ID = t.ListingID
    WHERE t.ListingID IS NULL
2 голосов
/ 16 ноября 2010

Я думаю, что вы, возможно, захотите переместить ListingTypeMatrix.ListingTypeID = '4' в предложение ON для ListingTypeMatrix OUTER JOIN. Предложение будет выглядеть следующим образом

LEFT OUTER JOIN ListingTypeMatrix ON Listing.ID = ListingTypeMatrix.ListingID
       AND ListingTypeMatrix.ListingTypeID = '4'

И вы удалили бы ListingTypeMatrix.ListingTypeID = '4' AND из предложения WHERE.

Это изменение вернет только строки из ListingTypeMatrix, которые = 4, и объединит результаты с остальной частью запроса. LEFT OUTER JOIN указывает, что строки из Listing и Locations не будут исключены, если строки не отображаются в ListingTypeMatrix.

2 голосов
/ 16 ноября 2010

Предполагая, что остальная часть вашего SQL корректна, просто добавьте нулевую проверку для ListingTypeID:

SELECT Listing.Title, Listing.MLS, COALESCE (Pictures.PictureTH, '../default_th.jpg') AS PictureTH, COALESCE (Pictures.Picture, '../default.jpg') AS Picture, Listing.ID, Listing.Description, Listing.Lot_Size, Listing.Building_Size, Listing.Bathrooms, Listing.Bedrooms, Listing.Address1, Listing.Address2, Listing.City, Locations.Abbrev, Listing.Zip_Code, Listing.Price, Listing.Year_Built, ListingTypeMatrix.ListingTypeID 
FROM Listing 
INNER JOIN Locations ON Listing.State = Locations.LocationID 
LEFT OUTER JOIN ListingTypeMatrix ON Listing.ID = ListingTypeMatrix.ListingID 
LEFT OUTER JOIN  Pictures ON Listing.ID = Pictures.ListingID 
WHERE (ListingTypeMatrix.ListingTypeID = '4' OR ListingTypeMatrix.ListingTypeID IS NULL) AND  
          ((Pictures.ID IS NULL) OR (Pictures.ID = 
                          (SELECT     MIN(ID) 
                            FROM          Pictures 
                            WHERE      (ListingID = Listing.ID)))) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...