2015-07-15 6 views
2

У меня проблема в Oracle SQL, которую я пытаюсь развернуть.SQL SELECT Значения сумм без учета дубликатов

Я проиллюстрирую пример. У меня есть три таблицы, которые я запрашивая:

Employees 
__________________________________________ 
| EmployeeID | Name      | 
| 1   | John Smith    | 
| 2   | Douglas Hoppalot   | 
| 3   | Harry Holiday    | 
... 



InternalCosts 
________________________________ 
| IntID | Amount | EmployeeID | 
| 1  | 10  |  1  | 
| 2  | 20  |  2  | 
| 3  | 30  |  1  | 
... 


ExternalCosts 
________________________________ 
| ExtID | Amount | EmployeeID | 
| 1  | 40  |  1  | 
| 2  | 50  |  2  | 
| 3  | 60  |  1  | 
... 

То, что я хочу, чтобы достичь является результатом одной строки на одного работника, с суммами каждого из своих внутренних и внешних издержек, т.е.

____________________________________________________________ 
| Name    | InternalCostTotal | ExternalCostTotal | 
| John Smith  | 40    | 100    | 
| Douglas Hoppalot | 20    | 50    | 
... 

The проблема заключается в том, что когда я запрашиваю таблицы InternalCosts и ExternalCosts, я получаю каждую перестановку затрат, а не только одну на одного сотрудника. Когда я группирую по имени сотрудника и суммирую количество полей, значения слишком высокие. То, что я пробовал:

SELECT emp.Name, sum(int.Amount), sum(ext.Amount) 
FROM Employees emp, 
    InternalCosts int, 
    ExternalCosts ext 
WHERE emp.EmployeeId = int.EmployeeID 
    and emp.EmployeeID = ext.EmployeeID 
GROUP BY emp.Name 

Приведенные выше примеры вернутся:

____________________________________________________________ 
| Name    | InternalCostTotal | ExternalCostTotal | 
| John Smith  | 80    | 200    | <- too high! 
| Douglas Hoppalot | 20    | 50    | 
... 

признательна за любую помощь/советы/мысли!

+0

проблема при подключении сотрудников с internalcosts вы получите два ряда при EmployeeID = 1 и когда вы присоединитесь к результирующей 2 строки с внешними кодами возвращают 4 строки, а затем вычисляют сумму. Поместите int.extid = int.intid в where where. –

ответ

2

Вы должны использовать подзапросы для int и ext для суммирования и присоединиться к подзапросам.

Я также предлагаю использовать явные JOIN и вместо таблицы, таблицы, таблицы

например,

SELECT emp.Name, int.Amount AS InternalCostTotal, ext.Amount AS ExternalCostTotal 
FROM Employees emp 
JOIN ( 
    SELECT EmployeeID, SUM(Amount) AS Amount 
    FROM InternalCosts 
    GROUP BY EmployeeID 
) int ON emp.EmployeeId = int.EmployeeID 
JOIN ( 
    SELECT EmployeeID, SUM(Amount) AS Amount 
    FROM ExternalCosts 
    GROUP BY EmployeeID 
) ext ON emp.EmployeeId = ext.EmployeeID 
+0

ДА! Это именно то, что мне нужно! Я даже не думал делать группировку и суммирование в подзапросах. Genius! Спасибо! –

1

Это должно сделать трюк:

SELECT emp.Name, NVL(IntAmount,0), NVL(ExtAmount,0) 
FROM Employees emp 
    LEFT JOIN 
    (SELECT EmployeeID, sum(Amount) as IntAmount 
    FROM InternalCosts GROUP BY EmployeeID) int 
    ON emp.EmployeeID = int.EmployeeID 
    LEFT JOIN 
    (SELECT EmployeeID, sum(Amount) as ExtAmount 
    FROM ExternalCosts GROUP BY EmployeeID) ext 
    ON emp.EmployeeID = ext.EmployeeID 

Обратите внимание, что нормализация структуры таблицы может помочь вам в этом случае и в будущем, вероятно (и это я имею в виду слияние внешних и внутренних издержек в одну таблицу, при условии, что это возможно, конечно).

+0

Oracle не поддерживает «AS» в псевдонимах таблиц. Если вы удалите их, ваш запрос будет работать. – Boneist

+0

Спасибо, слишком много RDMSes;) –

+0

Спасибо! К сожалению, запрос, над которым я работаю, намного сложнее, чем в моем примере, и динамически построен в приложении PowerBuilder, поэтому работа с объединениями не является чем-то, к чему я хочу попасть в этом случае. Обычно я всегда стараюсь использовать объединения, но я предпочитаю это. –

0

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

Cheers!

+0

Как насчет добавления запроса в соответствии с вашим предложением для поддержки вашего ответа? Это даст более четкое представление о том, что вы пытаетесь сказать. –

+0

Спасибо, я получил решение от одного из других ответов, но я очень признателен, что вы ответили на мой вопрос! –

0

Тест

SELECT t1.emp_name,inernalAmount,sum(ext.Amount) as externalAmount from 
(
SELECT emp.EmployeeID,emp.Name, sum(int.Amount) as internalAmount 
FROM Employees emp inner join InternalCosts int on emp.EmployeeId = int.EmployeeID 
) t1 inner join ExternalCosts ext on t1.EmployeeID = ext.EmployeeID 
GROUP BY t1.Name,internalAmount 
+0

Ваш запрос не работает, как есть. Вам не хватает группы из вашего подзапроса, плюс t1.emp_name не существует (t1.name?), И вы ошибаетесь «internalamount» в списке столбцов внешнего выбора. – Boneist

+1

Спасибо, я получил решение для своей проблемы по одной из других проблем, но было очень приятно ответить на мой вопрос. –

2

SQL Fiddle

Oracle 11g R2 Настройка схемы:

CREATE TABLE Employees (EmployeeID, Name) AS 
      SELECT 1, 'John Smith' FROM DUAL 
UNION ALL SELECT 2, 'Douglas Hoppalot' FROM DUAL 
UNION ALL SELECT 3, 'Harry Holiday' FROM DUAL; 

CREATE TABLE InternalCosts (IntID, Amount, EmployeeID) AS 
      SELECT 1, 10, 1 FROM DUAL 
UNION ALL SELECT 2, 20, 2 FROM DUAL 
UNION ALL SELECT 3, 30, 1 FROM DUAL; 

CREATE TABLE ExternalCosts (ExtID, Amount, EmployeeID) AS 
      SELECT 1, 40, 1 FROM DUAL 
UNION ALL SELECT 2, 50, 2 FROM DUAL 
UNION ALL SELECT 3, 60, 1 FROM DUAL; 

Query 1:

SELECT e.*, 
     (SELECT SUM(Amount) FROM InternalCosts i WHERE e.EmployeeID = i.EmployeeID) AS InternalCostTotal, 
     (SELECT SUM(Amount) FROM ExternalCosts x WHERE e.EmployeeID = x.EmployeeID) AS ExternalCostTotal 
FROM Employees e 

Results:

| EMPLOYEEID |    NAME | INTERNALCOSTTOTAL | EXTERNALCOSTTOTAL | 
|------------|------------------|-------------------|-------------------| 
|   1 |  John Smith |    40 |    100 | 
|   2 | Douglas Hoppalot |    20 |    50 | 
|   3 | Harry Holiday |   (null) |   (null) | 

Или (с помощью соединения):

WITH InternalTotals AS (
    SELECT EmployeeID, 
     SUM(Amount) AS InternalCostTotal 
    FROM InternalCosts 
    GROUP BY 
     EmployeeID 
), 
ExternalTotals AS (
    SELECT EmployeeID, 
     SUM(Amount) AS ExternalCostTotal 
    FROM ExternalCosts 
    GROUP BY 
     EmployeeID 
) 
SELECT e.EmployeeID, 
     i.InternalCostTotal, 
     x.ExternalCostTotal 
FROM Employees e 
     LEFT OUTER JOIN 
     InternalTotals i 
     ON (e.EmployeeID = i.EmployeeID) 
     LEFT OUTER JOIN 
     ExternalTotals x 
     ON (e.EmployeeID = x.EmployeeID); 
+0

Отлично, спасибо! Это было действительно полезно в поиске решения! –

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