Как гарантировать, что внешнее соединение с фильтром по-прежнему возвращает все нужные строки? - PullRequest
0 голосов
/ 08 ноября 2011

Представьте, что у меня есть две таблицы в БД, например:

products:    
product_id  name
----------------
1           Hat
2           Gloves
3           Shoes

sales:
product_id  store_id  sales
----------------------------
1           1         20
2           2         10

Теперь я хочу сделать запрос, чтобы вывести список ВСЕХ продуктов и их продаж для store_id = 1. Моя первая попытка сделать этоиспользовать левое соединение и отфильтровать до нужного store_id или нулевого store_id, если товар не получил продаж при store_id = 1, поскольку я хочу, чтобы все продукты были в списке:

SELECT name, coalesce(sales, 0)
FROM products p
LEFT JOIN sales s ON p.product_id = s.product_id
WHERE store_id = 1 or store_id is null;

Конечно, это работает не так, как задумано, вместо этого я получаю:

name   sales
---------------
Hat    20
Shoes  0

Без перчаток!Это связано с тем, что перчатки получили продажи, но не при store_id = 1, поэтому предложение WHERE отфильтровало их.

Как я могу получить список ВСЕХ продуктов и их продаж для определенного магазина?

Вот несколько запросов для создания тестовых таблиц:

create temp table test_products as 
select 1 as product_id, 'Hat' as name;
insert into test_products values (2, 'Gloves');
insert into test_products values (3, 'Shoes');
create temp table test_sales as
select 1 as product_id, 1 as store_id, 20 as sales;
insert into test_sales values (2, 2, 10);

ОБНОВЛЕНИЕ: я должен отметить, что мне известно об этом решении:

SELECT name, case when store_id = 1 then sales else 0 end as sales
FROM test_products p
LEFT JOIN test_sales s ON p.product_id = s.product_id;

однако это не такидеально ... на самом деле мне нужно создать этот запрос для инструмента BI таким образом, чтобы инструмент мог просто добавить предложение where к запросу и получить желаемые результаты.Вставка требуемого store_id в правильное место в этом запросе не поддерживается этим инструментом.Поэтому я ищу другие варианты, если они есть.

Ответы [ 2 ]

2 голосов
/ 08 ноября 2011

Добавьте условие WHERE в предложение LEFT JOIN, чтобы предотвратить пропадание строк.

SELECT p.name, coalesce(s.sales, 0)
FROM   products p
LEFT   JOIN sales s ON p.product_id = s.product_id
                   AND s.store_id = 1;

Изменить для дополнительного запроса:

Я полагаю, вы можете манипулировать элементами SELECT?Тогда это должно сделать работу:

SELECT p.name
      ,CASE WHEN s.store_id = 1 THEN coalesce(s.sales, 0) ELSE NULL END AS sales
FROM   products p
LEFT   JOIN sales s USING (product_id)

Также упрощен синтаксис объединения в этом случае.

1 голос
/ 08 ноября 2011

Я не близок к SQL, но попробую:

SELECT name, coalesce(sales, 0)
FROM products p
LEFT JOIN sales s ON p.product_id = s.product_id AND store_id = 1

Вам не нужно где-то в целом запросе, только при соединении

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