Mysql 如何在左侧联接上正确使用扩展约束,以便在左侧返回所有结果
我无法将去年的预算摘要视图转换为今年的预算摘要视图。以下是去年视图的SELECT语句,它返回正确的内容:Mysql 如何在左侧联接上正确使用扩展约束,以便在左侧返回所有结果,mysql,sql,left-join,Mysql,Sql,Left Join,我无法将去年的预算摘要视图转换为今年的预算摘要视图。以下是去年视图的SELECT语句,它返回正确的内容: SELECT b.Category AS Category, b.Amount AS Amount, SUM(e.Amount) AS Spent, (b.Amount - SUM(e.Amount)) AS Remaining FROM Budget AS b LEFT JOIN Expenditure AS e ON (
SELECT
b.Category AS Category,
b.Amount AS Amount,
SUM(e.Amount) AS Spent,
(b.Amount - SUM(e.Amount)) AS Remaining
FROM
Budget AS b LEFT JOIN Expenditure AS e
ON (
b.Category = e.BudgetCategory
AND e.Date < '2016-01-01'
AND e.Date > '2015-01-01'
AND b.Year = 2015
)
GROUP BY e.BudgetCategory
等等
今年的回报情况:Category | Amount | Spent | Remaining
--------------------------------------------
Contractors | 4000.00 | NULL | NULL
我希望它返回的内容(而支出结果仍然为0):
等等
我做错了什么?您需要按左联接的第一个表中的列进行聚合:
SELECT b.Category AS Category, b.amount,
SUM(e.Amount) AS Spent,
(b.Amount - SUM(e.Amount)) AS Remaining
FROM Budget b LEFT JOIN
Expenditure e
ON b.Category = e.BudgetCategory AND
e.Date < '2016-01-01' AND
e.Date >= '2015-01-01'
b.Year = 2015
GROUP BY b.Category, b.amount;
选择b.类别作为类别,b.金额,
已花费的金额(如金额),
(b.金额-剩余金额(e.金额))
从预算b左连接
支出e
b.类别=e.预算类别和
e、 日期<'2016-01-01'和
e、 日期>='2015-01-01'
b、 年份=2015年
按b.类别、b.金额分组;
小变化:
- 我将
子句中的条件更改为ON
。这似乎更合理=
- 我将
添加到b.amount
分组中
左联接的第一个表中的列进行聚合
:
SELECT b.Category AS Category, b.amount,
SUM(e.Amount) AS Spent,
(b.Amount - SUM(e.Amount)) AS Remaining
FROM Budget b LEFT JOIN
Expenditure e
ON b.Category = e.BudgetCategory AND
e.Date < '2016-01-01' AND
e.Date >= '2015-01-01'
b.Year = 2015
GROUP BY b.Category, b.amount;
选择b.类别作为类别,b.金额,
已花费的金额(如金额),
(b.金额-剩余金额(e.金额))
从预算b左连接
支出e
b.类别=e.预算类别和
e、 日期<'2016-01-01'和
e、 日期>='2015-01-01'
b、 年份=2015年
按b.类别、b.金额分组;
小变化:
- 我将
子句中的条件更改为ON
。这似乎更合理=
- 我将
添加到b.amount
分组中
这是一个小错误。您没有按
b.Category
分组,而是错误地按e.BudgetCategory
分组
SELECT
b.Category AS Category,
b.Amount AS Amount,
SUM(e.Amount) AS Spent,
(b.Amount - SUM(e.Amount)) AS Remaining
FROM
Budget AS b LEFT JOIN Expenditure AS e
ON (
b.Category = e.BudgetCategory
AND e.Date < '2016-01-01'
AND e.Date > '2015-01-01'
)
WHERE b.Year = 2015
GROUP BY b.Category;
选择
b、 类别作为类别,
b、 金额作为金额,
已花费的金额(如金额),
(b.金额-剩余金额(e.金额))
从…起
预算为b左,支出为e
在(
b、 类别=e.BudgetCategory
和e.日期<'2016-01-01'
和e.日期>'2015-01-01'
)
其中b.年份=2015年
按b类分组;
为了可读性,我将b.Year
上的标准移动到WHERE
,因为它不是支出的外部联接的标准
顺便问一下,Category
是表Budget
的唯一键吗?否则,您将获得任意选择的类别金额之一。也许您更希望使用聚合,例如SUM(b.Amount)
。这是一个小错误。您没有按b.Category
分组,而是错误地按e.BudgetCategory
分组
SELECT
b.Category AS Category,
b.Amount AS Amount,
SUM(e.Amount) AS Spent,
(b.Amount - SUM(e.Amount)) AS Remaining
FROM
Budget AS b LEFT JOIN Expenditure AS e
ON (
b.Category = e.BudgetCategory
AND e.Date < '2016-01-01'
AND e.Date > '2015-01-01'
)
WHERE b.Year = 2015
GROUP BY b.Category;
选择
b、 类别作为类别,
b、 金额作为金额,
已花费的金额(如金额),
(b.金额-剩余金额(e.金额))
从…起
预算为b左,支出为e
在(
b、 类别=e.BudgetCategory
和e.日期<'2016-01-01'
和e.日期>'2015-01-01'
)
其中b.年份=2015年
按b类分组;
为了可读性,我将b.Year
上的标准移动到WHERE
,因为它不是支出的外部联接的标准
顺便问一下,Category
是表Budget
的唯一键吗?否则,您将获得任意选择的类别金额之一。也许您更希望使用聚合,例如SUM(b.Amount)
。是表预算的唯一键(可能是主键)
吗?或者对于同一类别
,是否会有多条预算
记录?类别
是否是表预算
的唯一键(可能是主键)?或者同一个类别可以有多个预算
记录
?我发现查询也可以通过按e.BudgetCategory和b.Category分组或仅按b.Category分组来工作。我最初是按e.BudgetCategory进行分组的,因为e表中的内容正在汇总。这里对逻辑的高层次解释是什么。为什么group by需要位于联接的任何一侧?@Shadouts:这是因为您要联接外部支出表。如果在该表中找不到给定日期范围内Budget.Category的匹配项,则会得到一条所有字段均为空的伪记录,包括BudgetCategory。所以你没有按你实际查找的类别(Budget.category)分组。@Shadouts:至于“按e.BudgetCategory和b.category分组,或者仅按b.category分组”,这是因为正如你在对我的回答的评论中所说,一年中每个类别只有一个记录。如果不是这样的话,你会得到一个类别的金额任意选择。Gordon不知道category+year在您的表中是唯一的,所以他将budget.amount放在GROUP BY子句中,以确保不会悄悄地引入这样的错误。此外,在GROUPBY中包含此列可以保证查询在MySQL中仅在打开_FULL_GROUP_BY模式的情况下运行;我发现查询也可以通过按e.BudgetCategory和b.Category分组,或者仅按b.Category分组。我最初是按e.BudgetCategory进行分组的,因为e表中的内容正在汇总。这里对逻辑的高层次解释是什么。为什么group by需要位于联接的任何一侧?@Shadouts:这是因为您要联接外部支出表。如果在该表中找不到给定日期范围内Budget.Category的匹配项,则会得到一条所有字段均为空的伪记录,包括BudgetCategory。所以你没有按你实际查找的类别(Budget.category)分组。@Shadouts:至于“按e.BudgetCategory和b.category分组,或者仅按b.category分组”,这是因为正如你在对我的回答的评论中所说,一年中每个类别只有一个记录。如果不是这样的话,你会得到一个类别的金额