И синтаксис во внешнем объединении?

Это небольшой фрагмент гораздо большего запроса, который, как я обнаружил, является проблемой.

Я пытаюсь добавить фильтр к моему внешнему соединению в дополнение к первичному ключу. Проблема в том, что я получаю результаты, которые имеют StatusCode, отличный от 0 или 1, как если бы он игнорировал фильтр.

SELECT * 
FROM Products P
LEFT OUTER JOIN OrderDetails OD ON OD.SkuNum = P.SkuNum
LEFT OUTER JOIN OrderHeader OH ON (OD.ShipmentNum = OH.ShipmentNum
                               AND (OH.StatusCode = 0 OR OH.StatusCode = 1))
WHERE P.SkuNum = XXXX

Обратите внимание, что если я добавлю этот оператор (OH.StatusCode = 0 ИЛИ OH.StatusCode = 1) в предложение where, он отфильтрует весь набор результатов по этим критериям, что тоже не то, что мне нужно.

Для этого соединения на простом английском я пытаюсь сказать: "Дайте мне все продукты и другие вещи, не перечисленные здесь. Если есть какие-либо поставки для этого продукта, дайте мне все детали для них, где статус доставки 1 или 0"

Мой синтаксис неверен или я что-то упустил? Благодарю.

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

6 ответов

Решение

Обычно у вас всегда будет OrderHeader для данного OrderDetail, но у вас может не быть его со статусом 0, 1.

Делая левое соединение, вы получаете все для этого конкретного Sku, а затем, если заголовок заказа не имеет статуса 0, 1, эти столбцы будут NULL,

Я думаю, ты хочешь ВНУТРЕННЕГО СОЕДИНЕНИЯ. Но тогда это, как правило, было бы равносильно помещению всего в ГДЕ, поэтому я уверен, что вы полностью описываете, что вы хотите получить здесь.

После просмотра изменений попробуйте это:

SELECT * 
FROM Products P
LEFT JOIN (
    SELECT OD.SkuNum, OD.ShipmentNum, etc.
    FROM OrderDetails OD
    INNER JOIN OrderHeader OH
        ON OD.ShipmentNum = OH.ShipmentNum
            AND (OH.StatusCode = 0 OR OH.StatusCode = 1)
) AS Orders ON Orders.SkuNum = P.SkuNum
WHERE P.SkuNum = XXXX

Вам не нужна производная таблица здесь.

Размещая ON OD.SkuNum = P.SkuNum последний пункт LEFT JOIN По продуктам логически бывает последним.

SELECT *
FROM   Products P
       LEFT OUTER JOIN OrderDetails OD
                       INNER JOIN OrderHeader OH
                         ON OD.ShipmentNum = OH.ShipmentNum
                            AND OH.StatusCode IN ( 0, 1 )
         ON OD.SkuNum = P.SkuNum
WHERE  P.SkuNum = 'XXXX'

Делая левое соединение, вы говорите, что хотите получить все детали заказа, где skunum = xxxx, независимо от того, есть ли совпадения в таблице заголовков заказа.

Основываясь на вашем запросе и простом английском описании, для меня это звучит так, будто вы хотите внутреннее соединение. Но, возможно, я недостаточно понимаю или у меня недостаточно информации. Внутреннее соединение вернет только все детали заказа, если отгрузка имеет статус 1 или 0 и скунум совпадает.

Попробуй это:

SELECT * 
FROM Products P
LEFT OUTER JOIN 
  ( OrderDetails OD 
     INNER JOIN OrderHeader OH ON (OD.ShipmentNum = OH.ShipmentNum
                               AND (OH.StatusCode = 0 OR OH.StatusCode = 1))
  ) ON OD.SkuNum = P.SkuNum
WHERE P.SkuNum = XXXX
SELECT  *
FROM    Products P
        LEFT JOIN (
            SELECT  OD.*
            FROM    OrderHeader OH
                    INNER JOIN OrderDetails OD
                        ON OH.ShipmentNum = OD.ShipmentNum
            WHERE   OH.StatusCode IN (0,1)
        ) as orders    
            ON P.SkuNum = orders.SkuNum
WHERE    P.SkuNum = XXXX            

Не уверен, что это то, что вы ищете:

SELECT *
FROM OrderHeader OH
LEFT OUTER JOIN OrderDetails OD ON OD.ShipmentNum = OH.ShipmentNum AND OD.SkuNum = XXXX
WHERE OH.StatusCode IN (0, 1)

Ваше заявление на простом английском языке, кажется, указывает на то, что вы ищете конкретную посылку. Возможно, вы захотите добавить shipmentnum к предложению where.

Другие вопросы по тегам