我需要从两个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;
我只使用此查询获取两个视图中的记录,但我需要根据车辆编号选择视图中没有收入或费用的记录。请帮忙。
答案 0 :(得分:1)
让我们首先澄清结果集的规范。我正在拼写这个,因为我坚信良好的SQL自然会从明确的规范中流出。
因此,我们首先需要生成一个vnumbers的权威列表。这很容易
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有一行。
如果你很聪明,你将独立地对每一个进行单元测试。
现在,我们通过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
这可能比你讨价还价更多。但这是获得所需结果集的结构化和可预测的方式。