Запрос SQL Server INNER JOIN - пропущенные записи - PullRequest
0 голосов
/ 26 января 2012

FYI - этот запрос выполняется из Excel. У меня есть подсказки для установки диапазона дат.

вот оригинальный рабочий запрос, который я получил от кого-то:

SELECT 
   SalesInvoiceItems.FreeTextItem, SalesInvoiceItems.Product,   
   SalesInvoiceItems.ItemDescription, SalesInvoiceItems.Quantity, 
   SalesInvoiceItems.ItemValue, Customers.CustomerId, Customers.CustomerName, 
   SalesInvoices.SalesInvoiceId, SalesInvoices.EffectiveDate, Countries.CountryId, 
   SalesInvoiceItems.ItemType
FROM 
   Winman.dbo.Countries Countries, Winman.dbo.Customers Customers, 
   Winman.dbo.Products Products, Winman.dbo.SalesInvoiceItems SalesInvoiceItems, 
   Winman.dbo.SalesInvoices SalesInvoices
WHERE 
    Customers.Customer = SalesInvoices.Customer 
    AND SalesInvoiceItems.SalesInvoice = SalesInvoices.SalesInvoice 
    AND Customers.Country = Countries.Country 
    AND ((SalesInvoices.SystemType='F') 
    AND (SalesInvoiceItems.ItemType<>'T') 
    AND (SalesInvoices.EffectiveDate>=? And SalesInvoices.EffectiveDate<=?) 
    AND (SalesInvoiceItems.ItemValue<>$0))
ORDER BY 
    SalesInvoiceItems.Quantity DESC

Важным битом здесь является ItemType (это может быть только T, исключая, P - для продуктов и N - для произвольных текстовых позиций)

Мне нужно было добавить таблицу Products, чтобы получить ProductID. Очевидно добавление приведенного ниже кода в предложение WHERE:

AND Products.Product = SalesInvoiceItems.Product 

не сможет вызвать произвольный текстовый элемент, так как это не продукты.

Поэтому я переписал запрос с JOIN, надеясь, что это решит мою проблему (вызовет записи типа P и N):

SELECT 
    Products.ProductId, 
    SalesInvoiceItems.FreeTextItem, 
    SalesInvoiceItems.Product, 
    SalesInvoiceItems.ItemDescription, 
    SalesInvoiceItems.Quantity, 
    SalesInvoiceItems.ItemValue, 
    Customers.CustomerId, 
    Customers.CustomerName, 
    SalesInvoices.SalesInvoiceId, 
    SalesInvoices.EffectiveDate, 
    Countries.CountryId, 
    SalesInvoiceItems.ItemType
FROM 
    Winman.dbo.SalesInvoiceItems AS SalesInvoiceItems 
INNER JOIN 
    Winman.dbo.Products AS Products ON Products.Product = SalesInvoiceItems.Product  
INNER JOIN 
    Winman.dbo.SalesInvoices AS SalesInvoices ON SalesInvoices.SalesInvoice= SalesInvoiceItems.SalesInvoice
INNER JOIN 
    Winman.dbo.Customers AS Customers ON Customers.Customer = SalesInvoices.Customer 
INNER JOIN 
    Winman.dbo.Countries AS Countries ON  Countries.Country = Customers.Country 
WHERE 
    ((SalesInvoices.SystemType='F') 
     AND (SalesInvoiceItems.ItemType<>'T') 
     AND (SalesInvoices.EffectiveDate >= ? And SalesInvoices.EffectiveDate <= ?) 
     AND (SalesInvoiceItems.ItemValue <> $0)
    )
ORDER BY 
    SalesInvoiceItems.Quantity DESC

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

Ответы [ 2 ]

2 голосов
/ 26 января 2012

Ваш старый запрос использует синтаксис старого стиля JOIN. Хорошо полностью отказаться от этого неявного (внутреннего) объединения в пользу явного объединения.

При использовании явных объединений теперь у вас есть выбор между INNER и OUTER объединениями ( ref. MSDN ).

Внутренние объединения возвращают строки только тогда, когда есть хотя бы одна строка из обоих таблицы, соответствующие условию соединения. Внутренние соединения устраняют ряды которые не совпадают со строкой из другой таблицы. Внешние соединения, однако вернуть все строки хотя бы из одной таблицы или представления упоминается в предложении FROM, если эти строки встречаются с WHERE или ИМЕЮЩИЕ условия поиска.

Поэтому в ответ на ваш вопрос измените INNER JOIN s на LEFT JOIN s

0 голосов
/ 26 января 2012

Не уверен, что я правильно понимаю, но попробуйте изменить:

INNER JOIN Winman.dbo.Products AS Products ON ...

на:

LEFT JOIN Winman.dbo.Products AS Products ON ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...