从 MySQL 中的两个视图中选择而不留下记录
Posted
技术标签:
【中文标题】从 MySQL 中的两个视图中选择而不留下记录【英文标题】:Select from two views in MySQL without leaving records 【发布时间】:2014-04-29 12:35:07 【问题描述】:我需要从两个 mysql 视图中进行选择,它们是收入和费用视图,我需要它,这样如果我没有该记录的费用,它应该为 0,收入也是如此。
这是我目前的查询:
select e.v_name,e.v_number,sum(e.cost) Expenses, sum(i.income)Income from expenses_view e,
income_view i where i.v_number = e.v_number
group by v_number;
我只使用此查询获取两个视图中的记录,但我需要根据车辆编号从视图中选择既没有收入也没有费用的记录。
【问题讨论】:
不要使用隐式(逗号)连接语法。请参阅正确的 JOIN 语法。一切都会变得清晰。此外,必须有另一个表 - 存储所有资源的 PK,无论它们包含在任一表中。 【参考方案1】:让我们首先阐明结果集的规范。我之所以要详细说明这一点,是因为我坚信良好的 SQL 会自然而然地源自清晰的规范。
-
您希望每行 (v_name,v_number) 显示收入和支出的总和,零表示其中没有任何一个。
收入和支出来自不同的表。
您没有(至少您没有在问题中披露)包含 (v_name,v_number) 值的最终列表的单独表格。
因此,我们首先需要生成您的 v_number 的最终列表。这很容易
SELECT DISTINCT v_name, v_number FROM (
SELECT v_name, v_number FROM expenses_view
UNION
SELECT v_name, v_number FROM income_view
) AS u
现在看,这是一种非常可怕的方法。我们需要的是一个包含所有人员记录的表。但是不要紧。有时企业软件因为数据隐藏而需要这种东西。
接下来我们需要总结一下收入和支出。这将像这样工作:
SELECT v_number, SUM(cost) AS cost FROM expenses_view GROUP BY v_number
和
SELECT v_number, SUM(income) AS income FROM expenses_view GROUP BY v_number
您必须在加入这些表之前使用SUM()
进行聚合,因为 JOIN 操作会产生组合爆炸。如果您在 JOIN 之后执行 SUM()
操作,您的总和将太大;您将多次使用每个详细记录。
所以,这里我们有三个查询,每个查询生成一个虚拟表,每个 v_number 有一行。
-
v_number -> v_name
v_number -> 费用
v_number -> 收入
如果你很聪明,你会独立地对其中的每一个进行单元测试。
现在,我们使用 LEFT JOIN 将它们连接在一起,以获得您想要的结果集。我们需要 LEFT JOIN,因为普通的 JOIN 会忽略没有收入和支出记录的行。
SELECT v.v_name, v.v_number,
IFNULL(e.cost,0) AS cost,
IFNULL(i.income,0) AS income
FROM (
/* first virtual table */
) AS v
LEFT JOIN (
/* second virtual table */
) AS e ON v.v_number = e.v_number
LEFT JOIN (
/* third virtual table */
) AS i ON v.v_number = i.v_number
看看情况如何?我们生成我们需要的清单(人员、成本、收入),然后将这些清单组合在一起以获得最终结果。
这是实际的查询。
SELECT v.v_name, v.v_number,
IFNULL(e.cost,0) AS cost,
IFNULL(i.income,0) AS income
FROM (
/* first virtual table */
SELECT DISTINCT v_name, v_number FROM (
SELECT v_name, v_number FROM expenses_view
UNION
SELECT v_name, v_number FROM income_view
) AS u
) AS v
LEFT JOIN (
/* second virtual table */
SELECT v_number, SUM(cost) AS cost FROM expenses_view GROUP BY v_number
) AS e ON v.v_number = e.v_number
LEFT JOIN (
/* third virtual table */
SELECT v_number, SUM(income) AS income FROM expenses_view GROUP BY v_number
) AS i ON v.v_number = i.v_number
这可能有点超出您的预期。但这是获得所需结果集的结构化且可预测的方式。
【讨论】:
以上是关于从 MySQL 中的两个视图中选择而不留下记录的主要内容,如果未能解决你的问题,请参考以下文章