#sql-server #join
#sql-server #Присоединиться
Вопрос:
У меня проблема с получением результата из sql-запроса. Мне нужен результат из двух предложений where. Я работаю с SQLServer2014
таблица1: Продукт
ProductID
1
2
3
4
5
таблица 2: Поставщик
SupplierID
1
2
3
table3: Product_Supplier
ProductSupplierID|ProductID|SupplierID|Reference
1 |1 |1 |Ref001
2 |1 |2 |Ref002
3 |2 |1 |Ref003
4 |3 |2 |Ref004
5 |4 |2 |Ref005
Я хочу получить результат, когда я устанавливаю:
где (ProductID<4) и (SupplierID= 2)
Я должен получить в результате: весь продукт под идентификатором продукта 4, связанный с идентификатором поставщика 2, если он не существует в Product_Supplier, я должен получить Reference = Null
ProductID|SupplierID|Reference
1 |2 |Ref002
2 |2 |Null
3 |2 |Ref004
Я запускаю некоторый sql-скрипт, но не могу получить правильный результат
select a.ProductID, b.SupplierID, C.Reference from Product as a
left outer join Product_Supplier as c on c.ProductID= a.ProductID
left outer join Supplier as B on b.SupplierID = c.SupplierID
where a.ProductID<4 and b.SupplierID=2
Ответ от Феликса Памиттана:
SELECT
t.*,
ps.Reference
FROM (
SELECT *
FROM Product
CROSS JOIN Supplier
WHERE
ProductID < t.ProductID
AND SupplierID = t.SupplierID
) t
LEFT JOIN Product_Supplier ps
ON ps.ProductID = t.ProductID
AND ps.SupplierID = t.SupplierID
В этом скрипте я не могу ввести add runtime код where. Когда я могу установить where в конце sql, конечный пользователь может ввести параметры where.
SELECT
t.*,
ps.Reference
FROM (
SELECT *
FROM Product
CROSS JOIN Supplier
--WHERE
-- ProductID < t.ProductID
-- AND SupplierID = t.SupplierID
) t
LEFT JOIN Product_Supplier ps
ON ps.ProductID = t.ProductID
AND ps.SupplierID = t.SupplierID
where t.ProductID < 4
and t.SupplierID=2
Я проверю это последним на реальной базе данных.
Комментарии:
1.
SELECT * FROM Product_Supplier WHERE ProductId < 4 AND SupplierID = 2
2. Проблема в том, что я могу получить вторую строку (2,2, null)
3. Просто поправьте меня, если я ошибаюсь; в Product_Supplier нет кортежей, где ProductID и SupplierID равны 2… Если кортеж отсутствует, он никогда не будет выбран. То есть, когда таблица Product объединяется с Product_Supplier , тогда идентификатор поставщика будет равен null, и аналогично для кортежа с SupplierID=2, тогда ProductID будет равен null. Вашим лучшим выбором может быть цикл For? Но это довольно некрасиво.
4. @JonSick : правильно. Я застрял с этим.
Ответ №1:
Сначала вам нужно получить все комбинации Product
s и Supplier
s. Сделайте это, выполнив a CROSS JOIN
. Наконец, выполните a LEFT JOIN
в Product_Supplier
таблице:
SELECT
t.*,
ps.Reference
FROM (
SELECT *
FROM #Product
CROSS JOIN #Supplier
WHERE
ProductID < 4
AND SupplieIrD = 2
) t
LEFT JOIN #Product_Supplier ps
ON ps.ProductID = t.ProductID
AND ps.SupplierID = t.SupplieIrD
Комментарии:
1. Я думаю, что это правильный путь. Могу ли я также установить предложения where в псевдониме t?
2. Что вы имеете в виду? Я помещаю
WHERE
предложение вCROSS JOIN
, чтобы минимизировать его результат, прежде чем выполнять aLEFT JOIN
в другой таблице.
Ответ №2:
Проблема b.SupplierID = 2
в критериях. Поскольку b (Supplier) ссылается на c (таблица ссылок), это отрицает левое соединение в b, если запись не существует в c.
Вместо этого вы можете переместить критерий в соединение:
select a.ProductID, b.SupplierID, C.Reference from Product as a
join Supplier as B on b.SupplierID = 2 -- moved criterium
left join Product_Supplier as c on c.ProductID= a.ProductID and c.SupplierID=b.SupplierID
where a.ProductID<4
Поскольку явные данные supplier
не требуются, вы также можете полностью исключить это объединение и вместо этого жестко указать «2» в части выбора (вместе с использованием его в качестве дополнительного критерия в объединении)
select a.ProductID, 2, C.Reference from Product as a
left join Product_Supplier as c on c.ProductID= a.ProductID and c.SupplierID=2 -- moved criterium
where a.ProductID<4
Ответ №3:
Попробуйте это:
SELECT ps.ProductSupplierID, s.SupplierID, ps.Reference
FROM Product_Supplier ps
LEFT JOIN Product p ON ps.ProductID = p.ProductID
LEFT JOIN Supplier s ON ps.SupplierID = s.SupplierID
WHERE p.ProductID < 4
AND s.SupplierID = 2
Возможно, вам удастся избежать INNER JOINs
объединения вместо ОБЪЕДИНЕНИЯ СЛЕВА, но попробуйте LEFT JOINS
первое, и если это сработает, попробуйте INNER JOINs
просто посмотреть. Вы не получаете свои Null
значения из-за вашего JOINs
I believe.
Редактирование приведенного выше запроса должно дать вам правильные результаты. Вам нужно проверить и убедиться, что у вас действительно есть запись, которая попадает в вашу категорию, которую, по вашему мнению, вы делаете. Начните с удаления части WHERE
предложения построчно. Когда вы удаляете строку предложения и появляется запись, вы знаете, что нашли ошибку.
Комментарии:
1. Это только моя проблема, я хочу получить нулевые значения.
2. @Ravaut123 Не сработал ли приведенный выше запрос? Этот запрос должен выдать вам ваши нулевые значения.
3. Нет, я только меняю p.ProductID> 4 на p.ProductID < 4. Но никаких нулевых значений
4. @Ravaut123 О, вау. Я не могу поверить, что не видел, что вы написали почти точный запрос, который я вам дал. Мой плохой! Позвольте мне попробовать что-нибудь еще очень быстро
5. @Ravaut123 На самом деле, вам нужно использовать запрос, который я написал выше. В вашем запросе вы сначала выбираете из таблицы Product. Сначала вам нужно выбрать из таблицы Product_Supplier, а затем ПРИСОЕДИНИТЬСЯ к другим таблицам.