2015-07-28 2 views
1

Я не знаю, подходит ли этот вопрос на этом форуме.упрощение запросов SQL Union

У меня есть огромный запрос:

SELECT threshold.id, brand.id, COUNT(brand.id), threshold 
FROM current_stock, article, product, brand, delivery, threshold 
    WHERE current_stock.article_id = article.id 
    AND article.product_product_code = product.product_code 
    AND product.brand_id = brand.id 
    AND article.delivery_id = delivery.id 
    AND delivery.store_id = 'E260' 
    AND threshold.brand_id = brand.id 
    GROUP BY brand.id 
    HAVING COUNT(brand.id) <= threshold 
UNION 
SELECT threshold.id, brand.id, 0, threshold 
FROM current_stock, article, product, brand, delivery, threshold 
    WHERE threshold.store_id = 'E260' 
    AND threshold.brand_id NOT IN (
     SELECT brand_id FROM current_stock, article, product, delivery 
     WHERE current_stock.article_id = article.id 
     AND article.product_product_code = product.product_code 
     AND article.delivery_id = delivery.id 
     AND delivery.store_id = 'E260') 

И я думаю, что это можно сделать лучше, но после целого дня попытки я не нашел лучший запрос дает тот же результат.

Для уточнения, у меня есть запас (с current_stock, статья, товар и доставка). У меня также есть пороговые значения. я хочу проверить каждый порог, если имеется данный минимальный запас акций для данного бренда.

Моя проблема в том, что если есть 0 товарного знака, первая часть запроса не будет заботиться о пороге этой марки. Вот почему я добавил uggly Union.

У кого-то есть идея для лучшего способа сделать это?


EDIT

Это то, что я сделал после чтения комментариев и ответов:

ВЫБРАТЬ t.id, b.id, t.threshold, граф (b.id) акций

FROM threshold t 
    inner join brand b on b.id = t.brand_id 
    left join product p on p.brand_id = b.id 
    inner join article a on a.product_product_code = p.product_code 
    inner join delivery d on d.id = a.delivery_id 
    inner join current_stock cs on cs.article_id = a.id 

WHERE 
    t.store_id = 'E260' AND 
    d.store_id = 'E260' 

GROUP BY b.id 
HAVING stock <= t.threshold 

Моя проблема заключается в том, что она не дает все threholds ... только те, которые имеют хотя бы один «current_stock». Возможно, я не понимаю, как работают соединения.

Вот пример пороговой таблицы:

| id | brand_id | threshold | 
----------------------------- 
| 1 | 86  |  1  | 
| 2 | 28  |  1  | 
| 3 | 12  |  1  | 

То, что я хочу, как результат этого:

# with 2 entries in 'current_stock' for the brand id 28, 1 for 12 and 0 for 86 

| t.id | b.id | threshold | stock | 
----------------------------------- 
| 1 | 86 | 1  | 0 | 
| 3 | 12 | 1  | 1 | 
+4

Вы должны начать с переписывания запросов с использованием правильного явного синтаксиса 'join' и псевдонимов таблиц. Это один из способов помочь другим понять ваш запрос. –

+0

@Gordon ok скоро отредактируйте –

+0

Если вы хотите включить бренды без статей, используйте 'LEFT JOIN' с' article'. – Barmar

ответ

1

отгадывания несколько частей, так как здесь вы использовали неявным присоединяется к вашему образцу. Явная версия будет выглядеть примерно так (если я правильно понял, как вы присоединяетесь к пороговой таблице).

SELECT 
t.id, 
b.id, 
COUNT(b.id), 
t.threshold 

FROM 
current_stock c 
inner join article a on a.id = c.article_id 
inner join delivery d on d.id = a.delivery_id 
inner join product p on p.product_code = a.product_product_code 
inner join brand b on b.id = p.brand_id 
inner join threshold t on t.brand_id = b.id 

WHERE 
d.store_id = 'E260' 

GROUP BY b.id 
HAVING COUNT(b.id) <= t.threshold 

Теперь, чтобы получить ваши результаты включают в себя строку, в которых нет никаких «статей», вы можете начать переход из внутреннего присоединяется к левому присоединяется. Однако вы не можете просто использовать left outer join article... в приведенном выше примере, потому что store_id в предложении WHERE просто вернет его обратно в псевдо-внутреннее соединение.

Вместо этого, есть ли другое поле, где вы можете присоединиться к таблице delivery от current_stock?

EDIT - 07/29/15

Я думаю, что вы близки, вы можете просто слишком много фильтров, и вы считая от «Ъ», когда разыскиваемый результат предполагает, что Вы должны быть подсчета от 'cs'. Попробуйте следующее:

SELECT t.id, b.id, t.threshold, count(cs.id) stock 

FROM 
threshold t 
inner join brand b on b.id = t.brand_id 
inner join product p on p.brand_id = b.id 
inner join article a on a.product_product_code = p.product_code 
left outer join delivery d on d.store_id = t.store_id 
left outer join current_stock cs on cs.article_id = a.id 

WHERE 
t.store_id = 'E260' 

GROUP BY b.id 
HAVING stock <= t.threshold 
+0

Что такое различие между использованием заявления о соединении и использованием предложения Where, как в вопросе? –

+0

Оптимизатор запросов должен в конечном итоге делать то же самое для обоих способов его написания, но для чтения человеком в настоящее время выигрывает синтаксис явного соединения (неявные объединения устаревают в более новых версиях РСУБД). – CactusCake

+0

И что произойдет для значений, которые не заполнены? Например, если нет товарного брэнда, какова будет стоимость COUNT (brand.id)? –

Смежные вопросы