Sql 服务器多次加入聚合
Sql Server Multiple Joins with Aggregate
我正在尝试修复继承代码中的错误。此查询旨在返回 amex_meal_amount_total of
,但它给出了 </code>。问题出在第二个连接上 - <code>EE table
中有三个关联项使聚合总计三行。
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
我很清楚开发人员试图在连接中使用 table 别名(例如 EE_AMEX)以将 sum
函数限制为加入。
在 EE table
中只有一行与此 ID
的 line_item_type_id 1
。当我删除其他连接语句时,它会带回预期的 </code>.</p>
<pre><code> 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
是否有直接的修复方法,或者我是否需要完全重组查询?
Table结构:
尽量让这个问题简单化
expense_report:
report_id(PK)
expense_expense:
report_id(FK,一对多)
meal_amount(可以是多行,每行 report_id)
taxi_amount(其他费用示例)
line_item_type_id(1 是 AMEX,2 是 OOP,每行可以任意)
在这种情况下,急诊室在 expense_expense 中有一个关联行,餐费为 33 美元,这正是我所期望的。
但是,其他费用(例如出租车等)有 3 个关联行。
当 运行 查询时,它会将其汇总为三行,因此意外的 $99。
谢谢。
如何将 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
如果您正在寻找第一个查询返回 99 美元的原因,让我们看看如何。
让 tables 定义为
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;
所以在第一个 left join with expense table 之后结果将是一行
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
记下这些列。第一个 table 的 meal_amount 重复,因为它与右侧的 2 行 table 连接。
因此,对其求和将得到 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
我正在尝试修复继承代码中的错误。此查询旨在返回 amex_meal_amount_total of
,但它给出了 </code>。问题出在第二个连接上 - <code>EE table
中有三个关联项使聚合总计三行。
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
我很清楚开发人员试图在连接中使用 table 别名(例如 EE_AMEX)以将 sum
函数限制为加入。
在 EE table
中只有一行与此 ID
的 line_item_type_id 1
。当我删除其他连接语句时,它会带回预期的 </code>.</p>
<pre><code> 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
是否有直接的修复方法,或者我是否需要完全重组查询?
Table结构:
尽量让这个问题简单化
expense_report:
report_id(PK)
expense_expense:
report_id(FK,一对多)
meal_amount(可以是多行,每行 report_id)
taxi_amount(其他费用示例)
line_item_type_id(1 是 AMEX,2 是 OOP,每行可以任意)
在这种情况下,急诊室在 expense_expense 中有一个关联行,餐费为 33 美元,这正是我所期望的。
但是,其他费用(例如出租车等)有 3 个关联行。
当 运行 查询时,它会将其汇总为三行,因此意外的 $99。
谢谢。
如何将 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
如果您正在寻找第一个查询返回 99 美元的原因,让我们看看如何。 让 tables 定义为
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;
所以在第一个 left join with expense table 之后结果将是一行
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
记下这些列。第一个 table 的 meal_amount 重复,因为它与右侧的 2 行 table 连接。 因此,对其求和将得到 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