从两个视图中选择mysql而不留下记录

时间:2014-04-29 12:35:07

标签: mysql view

我需要从两个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;

我只使用此查询获取两个视图中的记录,但我需要根据车辆编号选择视图中没有收入或费用的记录。请帮忙。

1 个答案:

答案 0 :(得分:1)

让我们首先澄清结果集的规范。我正在拼写这个,因为我坚信良好的SQL自然会从明确的规范中流出。

  1. 您希望每个(v_name,v_number)有一行显示收入和费用的总和,零显示其中任何一个都没有。
  2. 收入和支出来自不同的表格。
  3. 你没有(至少你没有在你的问题中披露)一个单独的表,其中包含(v_name,v_number)值的确切列表。
  4. 因此,我们首先需要生成一个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有一行。

    1. v_number - > v_name
    2. v_number - >成本
    3. v_number - >收入
    4. 如果你很聪明,你将独立地对每一个进行单元测试。

      现在,我们通过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
      

      这可能比你讨价还价更多。但这是获得所需结果集的结构化和可预测的方式。