为什么这个左外连接查询没有正常工作?

时间:2011-07-04 00:21:18

标签: sql postgresql left-join

我有一个看起来像这样的表:

peter=> \d aggregated_accounts_by_month
Table "public.aggregated_accounts_by_month"
  Column   |  Type   | Modifiers 
-----------+---------+-----------
 xtn_month | date    | 
 account   | text    | 
 commodity | text    | 
 amount    | numeric | 
Indexes:
    "idx_aggregated_accounts_by_month_account" btree (account)
    "idx_aggregated_accounts_by_month_month" btree (xtn_month)

另一张看起来像这样的表:

peter=> \d months
   Table "pg_temp_2.months"
  Column   | Type | Modifiers 
-----------+------+-----------
 xtn_month | date | 

months包含以下内容:

 xtn_month   
------------
 2011-01-01 
 2011-02-01 
 2011-03-01 
 2011-04-01 
 2011-05-01 
 2011-06-01 
 2011-07-01 

aggregated_accounts_by_month包含以下相关数据:

 xtn_month  |    account    | amount 
------------+---------------+--------
 2011-01-01 | Expenses:Fuel | 111.31
 2011-02-01 | Expenses:Fuel |  89.29
 2011-03-01 | Expenses:Fuel |  97.41
 2011-04-01 | Expenses:Fuel | 101.70
 2011-05-01 | Expenses:Fuel |   52.9
 2011-07-01 | Expenses:Fuel |  49.55

我正在尝试运行的查询是:

select 
    months.xtn_month,
    account,
    amount
from
    aggregated_accounts_by_month a
    left outer join months on months.xtn_month = a.xtn_month
where
    account = 'Expenses:Fuel'
order by
    xtn_month;

我想要这个查询做的是给我这些结果:

 xtn_month  |    account    | amount 
------------+---------------+--------
 2011-01-01 | Expenses:Fuel | 111.31
 2011-02-01 | Expenses:Fuel |  89.29
 2011-03-01 | Expenses:Fuel |  97.41
 2011-04-01 | Expenses:Fuel | 101.70
 2011-05-01 | Expenses:Fuel |   52.9
 2011-06-01 | Expenses:Fuel |
 2011-07-01 | Expenses:Fuel |  49.55

但它确实给了我这个:

 xtn_month  |    account    | amount 
------------+---------------+--------
 2011-01-01 | Expenses:Fuel | 111.31
 2011-02-01 | Expenses:Fuel |  89.29
 2011-03-01 | Expenses:Fuel |  97.41
 2011-04-01 | Expenses:Fuel | 101.70
 2011-05-01 | Expenses:Fuel |   52.9
 2011-07-01 | Expenses:Fuel |  49.55

我显然做错了什么。有任何想法吗?我在Mac OS X 10.6.7上运行PostgreSQL 9.0.4。

编辑:在考虑了这个之后,我需要不仅几个月而且还要对帐户进行外部联接。这个查询完全符合我的要求:

select
    xtn_month,
    account,
    coalesce(amount, 0)
from
    (
        select
            xtn_month,
            account
        from
        (
            select
                distinct xtn_month
            from
                aggregated_accounts_by_month
        ) x
        cross join
        (
            select
                distinct account
            from
                aggregated_accounts_by_month
        ) y
    ) z
    left outer join aggregated_accounts_by_month
        using (xtn_month, account)
where
    account = 'Expenses:Fuel'
order by
    xtn_month;

ypercube的答案是几乎正确,除了它没有填写account列。这个查询当然相当昂贵,那里有那个交叉产品。但是没关系,因为aggregated_accounts_by_month在超过四年的数据中有一些不到2000行。

2 个答案:

答案 0 :(得分:3)

两件事:

  • 颠倒LEFT JOIN
  • 中两个表格的顺序
  • 将条件从WHERE移至ON子句。

select 
    months.xtn_month,
    a.account,
    a.amount
from
    months 
    left outer join aggregated_accounts_by_month a
        on  months.xtn_month = a.xtn_month
        and a.account = 'Expenses:Fuel'
order by
    xtn_month;

答案 1 :(得分:0)

您的aggregated_accounts_by_month不包含2011-06-01。您可能实际上正在寻找完整的联接:

select 
    months.xtn_month,
    account,
    amount
from
    aggregated_accounts_by_month a
    full join months on months.xtn_month = a.xtn_month
where
    account = 'Expenses:Fuel'
order by
    xtn_month;

或者,左边连接作为另外两个答案建议,即months,然后是aggregated_accounts_by_month