Что делать с одним и тем же подзапросом, повторяющимся много раз в операторе выбора, если он включает внешнее условие - PullRequest
1 голос
/ 26 января 2012

Я постараюсь сделать это как можно более конкретным. У меня есть таблица, содержащая информацию о транзакциях по предметам. Возможные транзакции: покупка (type_id: 1) и продажа (type_id: 2). Действительно урезанная версия таблицы «Транзакции» выглядит следующим образом:

Transaction_ID Item_ID Transaction_Type_ID Количество Цена Дата

1, 1, 1, 50, 10, 6/1,

2, 2, 1, 40, 20, 13/1,

3, 1, 2, 10, 13, 14/1,

4, 2, 2, 20, 25, 3/2,

5, 1, 2, 20, 12, 20/2

У меня следующий запрос:

SELECT B.Item_ID
       B.Quantity - (SELECT SUM(Quantity) FROM Transactions A Where A.Item_ID = B.Item_ID AND A.Transaction_Type_ID = 2) AS 'Quantity Left'
       B.Price * (B.Quantity - (SELECT SUM(Quantity) FROM Transactions A Where A.Item_ID = B.Item_ID AND A.Transaction_Type_ID = 2)) AS 'Purchase Amount Left'
FROM   Transaction B
WHERE  B.Transaction_Type_ID = 1
AND    B.Quantity - (SELECT SUM(Quantity) FROM Transactions A Where A.Item_ID = B.Item_ID AND A.Transaction_Type_ID = 2) > 0

Как вы уже заметили, я пытаюсь получить все купленные предметы, которые еще есть в наличии. Также вы можете заметить, что раздражающий подзапрос повторяется дважды в предложении SELECT и один раз в предложении WHERE. Как я могу уменьшить это? Можно ли использовать WITH в начале оператора в этом случае?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 26 января 2012

ПРИСОЕДИНИТЬСЯ к агрегированной производной таблице?

SELECT 
    B.Item_ID
    B.Quantity - ISNULL(A.SUMQuantity, 0) AS 'Quantity Left',
    B.Price * (B.Quantity - ISNULL(A.SUMQuantity, 0)) AS 'Purchase Amount Left'
FROM  
    Transaction B
    LEFT JOIN
    (
     SELECT SUM(Quantity) AS SUMQuantity, Item_ID
     FROM Transaction 
     WHERE Transaction_Type_ID = 2
     GROUP BY Item_ID
    ) ON A.Item_ID = B.Item_ID
WHERE  
    B.Transaction_Type_ID = 1
    AND   
    B.Quantity - ISNULL(A.SUMQuantity, 0) > 0

Если у вас всегда есть строки, в которых Transaction_Type_ID = 2, вы можете удалить LEFT JOIN и ISNULL. В вашем текущем коде вы предполагаете, что у вас всегда есть строки.

Похоже, вы смешиваете сущности в одной таблице на основе Transaction_Type_ID. Простой SUM(Quantity) .. GROUP BY Item_ID будет более правильным, если - продажи <0 количество транзакции - запасы> 0 количество транзакций2

0 голосов
/ 26 января 2012

Это должно работать.Хотя не проверено:

SELECT B.Item_ID
       B.Quantity - C.Quantity AS 'Quantity Left'
       B.Price * (B.Quantity - C.Quantity) AS 'Purchase Amount Left'
FROM   Transaction B 
cross apply 
  SELECT SUM(Quantity) Quantity FROM Transactions A 
  WHERE A.Item_ID = B.Item_ID AND A.Transaction_Type_ID = 2) C
WHERE B.Transaction_Type_ID = 1 AND B.Quantity > C.Quantity
0 голосов
/ 26 января 2012

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

select Transaction_Type_ID, Item_ID
  , Quantity - QuantitySold
  , Value * (Quantity - QuantitySold)
from
(
  select B.Transaction_Type_ID, B.Item_ID
    , sum(case when B.Transaction_Type_ID = 1 then Quantity else 0 end) QuantityPurchased
    , sum(case when B.Transaction_Type_ID = 1 then Quantity * Price else 0 end) Value
    , sum(case when B.Transaction_Type_ID = 2 then Quantity else 0 end) QuantitySold
  from Transaction B
  group by B.Transaction_Type_ID, B.Item_ID
) x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...