2016-11-04 2 views
7

У меня есть что-то вроде запросалевое внешнее соединение только с первой строки

SELECT S.product_id, S.link, C.id AS category_id 
FROM Products P 
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1 
LEFT OUTER JOIN Categories C ON c.product_id = P.id 
WHERE P.active = 1 

Я отлично работает для меня до тех пор, как каждый продукт присваивается только в одной категории. Но если продукт присваивается многим категориям, он возвращает все возможные комбинации.

Могу ли я выбрать только первый и, если продукт не имеет какой-либо категории связь все еще должны быть возвращены с category_id = NULL

+6

'Первый, по каким критериям? – Lamak

+0

Вы можете добавить MIN или MAX и GROUP BY на category_id. Если это недостаточно, переместите Категории в подзапрос. – Stavr00

ответ

4

Простой способ заключается в использовании внешний применить, чтобы иметь коррелируют присоединиться, и сделать это топ 1 запрос. Таким образом, вы можете получить доступ ко всем столбцам соответствующей записи категории. В качестве примера я добавляю название категории:

select s.product_id, s.link, c.id as category_id, c.name as category_name 
from products p 
inner join seo s on s.product_id = p.id 
outer apply 
(
    select top 1 * 
    from categories cat 
    where cat.product_id = p.id 
    order by cat.id 
) c 
where p.active = 1 
and p.product_type = 1; 
+0

Используя Outer apply, вы также можете заказать любой столбец в таблице категорий, который, вероятно, нужен ему. – Magnus

3

Вы можете использовать GROUP BY для достижения этой цели наряду с Aggregate функции, наиболее вероятно MIN или MAX.

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

SELECT S.product_id, S.link, MIN(C.id) AS category_id 
FROM Products P 
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1 
LEFT OUTER JOIN Categories C ON c.product_id = P.id 
WHERE P.active = 1 
GROUP BY S.product_id, S.link 

Или максимум.

SELECT S.product_id, S.link, MAX(C.id) AS category_id 
FROM Products P 
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1 
LEFT OUTER JOIN Categories C ON c.product_id = P.id 
WHERE P.active = 1 
GROUP BY S.product_id, S.link 
1

Альтернативное решение с использованием подзапроса:

SELECT S.product_id, S.link, 
(
SELECT C.id FROM Categories C WHERE C.product_id = P.id AND 
ROW_NUMBER() OVER(ORDER BY /* your sort option goes here*/) = 1 
) AS category_id 
FROM Products P 
INNER JOIN SEO S ON S.product_id = P.id AND P.product_type = 1 
WHERE P.active = 1