2015-01-13 3 views
0

В нижеприведенном запросе возникают проблемы, когда у меня есть два левых соединения. Что происходит, суммы являются неправильными (повышенными) с обоими левыми соединениями. Когда я удаляю второе левое соединение, запрос выполняется правильно. Как запустить этот запрос со вторым левым соединением?Проблема с SUM с двумя LEFT JOINs

SELECT o.IdNoLocation, 
COUNT(DISTINCT o.EncodedId) AS "Frequency", 
ISNULL(SUM(o.Subtotal), 0) AS "Spend", 
ISNULL(SUM(os.Amount), 0) AS "Surcharges", 
ISNULL(SUM(od.Amount), 0) AS "Discounts" 
FROM ((tblOrder o 
LEFT JOIN tblOrderSurcharge os ON o.OrderId=os.OrderId) 
LEFT JOIN tblOrderDiscount od ON o.OrderId=od.OrderId) 
WHERE 
o.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31' 
AND o.IdNoLocation <> 'X' 
GROUP BY o.IdNoLocation 
+0

Можете ли вы предоставить образцы данных и ожидаемый результат? –

+4

Завышенный 'SUM()' из-за 'JOIN' указывает, что ваших критериев недостаточно для соответствия строк между таблицами 1: 1. Может ли 'o.OrderID' иметь несколько записей в' tblOrderDiscount'? –

+0

Да, при заказе (o.OrderID) может быть применено более одной скидки (от TblOrderDiscount). – marshpipes

ответ

0

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

Существует несколько подходов к «исправлению» этого, если вам нужны итоги, возвращенные в одном выражении.

Один из вариантов - использовать встроенные представления для выполнения итогов, а затем объединить строки. По существу, запускайте отдельные запросы, чтобы получить итоговые данные из каждой таблицы, а затем объедините результаты по уникальному ключу. Например:

SELECT o.IdNoLocation 
    , o.Frequency 
    , ISNULL(o.Spend, 0)  AS Spend 
    , ISNULL(s.Surcharges), 0) AS Surcharges 
    , ISNULL(s.Discounts), 0) AS Discounts 
    FROM (SELECT ooo.IdNoLocation 
       , COUNT(DISTINCT ooo.EncodedId) AS Frequency 
       , SUM(ooo.Subtotal) AS Spend 
      FROM tblOrder ooo 
      WHERE ooo.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31' 
      AND ooo.IdNoLocation <> 'X' 
     GROUP BY ooo.IdNoLocation 
     ) o 
    LEFT 
    JOIN (SELECT oso.IdNoLocation 
       , SUM(oss.Amount) AS Surcharges 
      FROM tblOrderSurcharge oss 
      JOIN tblOrder oso 
      ON oso.OrderId = oss.OrderId 
      WHERE oso.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31' 
      AND oso.IdNoLocation <> 'X' 
      GROUP BY oso.IdNoLocation 
     ) s 
    ON s.IdNoLocation = o.IdNoLocation 
    LEFT 
    JOIN (SELECT odo.IdNoLocation 
       , SUM(odd.Amount) AS Discounts 
      FROM tblOrderDiscount odd 
      JOIN tblOrder odo 
      ON odo.OrderId = odd.OrderId 
      WHERE odo.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31' 
      AND odo.IdNoLocation <> 'X' 
      GROUP BY odo.IdNoLocation 
     ) d 
    ON d.IdNoLocation = o.IdNoLocation 

(Это не проверяется, только стол проверил Запуск каждый из видовых рядных запросов (о, s, d) и проверить результаты от каждого из этих запросов, как вы ожидаете тогда.. , запустите весь запрос, чтобы объединить строки ... во внешнем запросе, мы сделаем «внешние» соединения и обработаем «отсутствующие» строки и заменим нули нулями)

Другой вариант - использовать коррелированные подзапросы в списке SELECT.

0

Чтобы понять, почему это не работает, запустите этот запрос:

SELECT o.IdNoLocation, 
o.EncodedId AS "Frequency", 
o.Subtotal AS "Spend", 
os.Amount AS "Surcharges", 
od.Amount AS "Discounts" 
FROM ((tblOrder o 
LEFT JOIN tblOrderSurcharge os ON o.OrderId=os.OrderId) 
LEFT JOIN tblOrderDiscount od ON o.OrderId=od.OrderId) 
WHERE 
o.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31' 
AND o.IdNoLocation <> 'X' 

«правильный» ответ должны использовать одну таблицу для обоего доплат и скидок. Я бы предположил, что это уже не вариант, но вы можете подделать его с представлением, которое выполняет UNION ALL между двумя таблицами.

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