2015-03-11 4 views
2

Я пытаюсь исправить ошибку в унаследованном коде. Этот запрос предназначен для возврата amex_meal_amount_total of $33, но он дает $99. Проблема связана со вторым соединением - в EE table есть три связанных элемента, которые составляют суммарную сумму в три строки.Множественные соединения Sql Server с агрегатом

SELECT ER.report_id, 
     Isnull(Sum(EE_AMEX.meal_amount), 0) AS amex_meal_amount_total 
FROM expense_report ER (nolock) 
     LEFT OUTER JOIN expense_expense EE_AMEX (nolock) 
        ON ER.report_id = EE_AMEX.report_id 
         AND EE_AMEX.line_item_type_id = 1 
     LEFT OUTER JOIN expense_expense EE_OOP (nolock) 
        ON ER.report_id = EE_OOP.report_id 
         AND EE_OOP.line_item_type_id = 2 
WHERE er.report_id = 9733 
GROUP BY ER.report_id 

Это для меня ясно, что разработчик пытается использовать псевдоним таблицы в соединении (напр. EE_AMEX), чтобы ограничить функцию sum условию в объединении.

Существует только одна строка в EE table с line_item_type_id 1 для этого ID. Когда я удаляю другой оператор объединения, он возвращает ожидаемый $33.

SELECT ER.report_id, 
     Isnull(Sum(EE_AMEX.meal_amount), 0) AS amex_meal_amount_total 
FROM expense_report ER (nolock) 
     LEFT OUTER JOIN expense_expense EE_AMEX (nolock) 
        ON ER.report_id = EE_AMEX.report_id 
         AND ee_oop.line_item_type_id = 1 
WHERE er.report_id = 9733 
GROUP BY ER.report_id 

Есть ли прямое исправление этого вопроса, или мне нужно полностью перестроить запросы?

Структура таблицы:

Попытка держать его просто на этот вопрос

expense_report:
REPORT_ID (ПК)

expense_expense:
REPORT_ID (ФК, один ко многим)
meal_amount (может быть несколько строк с количеством еды за отчет_ид) taxi_amount (пример других сборов)
line_item_type_id (1 АМЕХ, 2 ООП, может быть любым для каждой строки)

В этом случае ER имеет один связанную строку в expense_expense с едой отвечает за $ 33, так что это то, чего я ожидал.

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

При выполнении запроса он подводит его в течение трех строк, таким образом, неожиданный $ 99.

Спасибо.

+0

Почему вы вступления в ООП, когда нет использования этой таблицы? –

+0

Левое соединение в первом запросе похоже на ER.report_id = EE_AMEX.report_id AND (EE_OOP.line_item_type_id = 1 ИЛИ EE_OOP.line_item_type_id = 2). И вы получили результат во втором запросе. –

+0

@ Giorgi Nakeuri, для пробных целей я не включил полный запрос, он также извлекает агрегаты из EE_OOP. Спасибо – CutOffTies

ответ

1

Как насчет переезда sum в subquery? Вам, вероятно, понадобится сделать то же самое для вашего EE_OOP aggregate, но я не был уверен, что вы вытаскиваете из этого.

SELECT ER.report_id, 
     Isnull((SELECT Sum(meal_amount) 
       FROM expense_expense EE_AMEX (nolock) 
       WHERE EE_AMEX.report_id = ER.report_id 
         AND EE_AMEX.line_item_type_id = 1), 0) AS 
     amex_meal_amount_total 
FROM expense_report ER (nolock) 
     LEFT OUTER JOIN expense_expense EE_OOP (nolock) 
        ON ER.report_id = EE_OOP.report_id 
         AND EE_OOP.line_item_type_id = 2 
WHERE er.report_id = 9733 
+0

Спасибо, что ты-тосик. – CutOffTies

1

Если вы ищете, почему первый запрос возвратил 99 долларов США, давайте посмотрим, как это сделать. Впустил таблицы можно определить как

select 1 report_id into #expense_report; 

select * into #expense_expense from (
select 1 report_id, 33 meal_amount, 0 taxi_amount, 1 line_item_type_id 
union all 
select 1 report_id, 0 meal_amount, 33 taxi_amount, 2 line_item_type_id 
union all 
select 1 report_id, 0 meal_amount, 33 taxi_amount, 2 line_item_type_id) t; 

Таким образом, после первого левого присоединиться к расходной таблице результат будет один ряд

SELECT * 
FROM #expense_report ER (nolock) 
     LEFT OUTER JOIN #expense_expense EE_AMEX (nolock) 
        ON ER.report_id = EE_AMEX.report_id 
         AND EE_AMEX.line_item_type_id = 1 
WHERE er.report_id = 1; 

report_id report_id meal_amount taxi_amount line_item_type_id 
1    1   33   0    1 

Теперь второй слева объединение будет применен на этот результат, т.е. однострочное объединение в результат двойной строки, что приведет к 2 строкам.

SELECT * 
FROM #expense_report ER (nolock) 
     LEFT OUTER JOIN #expense_expense EE_AMEX (nolock) 
        ON ER.report_id = EE_AMEX.report_id 
         AND EE_AMEX.line_item_type_id = 1 
     LEFT OUTER JOIN #expense_expense EE_OOP (nolock) 
        ON ER.report_id = EE_OOP.report_id 
         AND EE_OOP.line_item_type_id = 2 
WHERE er.report_id = 1; 

report_id report_id meal_amount taxi_amount line_item_type_id report_id meal_amount taxi_amount line_item_type_id 
1 1 33 0 1 1 0 33 2 
1 1 33 0 1 1 0 33 2 

Обратите внимание на столбцы. Первый файл meal_amount таблицы повторяется, потому что он соединяется с двумя строками правой таблицы. Так что, взяв на себя сумму, это приведет к $ 66 не $ 33.

Если вы хотите, чтобы показать, как такси, и количество еды в один ряд, но другого столбца, затем используйте ниже запроса:

SELECT ER.report_id, 
     Isnull(Sum(case when EE_AMEX.line_item_type_id =1 then EE_AMEX.meal_amount end), 0) AS amex_meal_amount_total, 
     Isnull(Sum(case when EE_AMEX.line_item_type_id =2 then EE_AMEX.taxi_amount end), 0) AS amex_taxi_amount_total 
FROM #expense_report ER (nolock) 
     LEFT OUTER JOIN #expense_expense EE_AMEX (nolock) 
        ON ER.report_id = EE_AMEX.report_id 
WHERE er.report_id = 1 
GROUP BY ER.report_id 
Смежные вопросы