【问题标题】:PostgreSQL can't make Self JoinPostgreSQL 无法进行自加入
【发布时间】:2019-06-27 20:27:18
【问题描述】:

我有一张桌子:

| acctg_cath_id | parent | description |
| 1             | 20     | Bills       |
| 9             | 20     | Invoices    |
| 20            |        | Expenses    |
| 88            | 30     |
| 89            | 30     |
| 30            |        |

我想创建一个自我加入,以便将我的项目分组到一个父项下。

试过了,还是不行:

SELECT
    accounting.categories.acctg_cath_id,
    accounting.categories.parent

FROM accounting.categories a1, accounting.categories a2

WHERE a1.acctg_cath_id=a2.parent

我收到错误:invalid reference to FROM-clause entry for table "categories"

当我尝试时:

a.accounting.categories.acctg_cath_id
b.accounting.categories.acctg_cath_id

我收到错误:cross-database references are not implemented: a.accounting.categories.acctg_cath_id


期望的输出:

  • 费用(父级 20)
    • 账单(儿童 1)
    • 发票(儿童 9)

我在这里做错了什么?

【问题讨论】:

  • postgresql self join的可能重复
  • @emix 好吧,我尝试了 a.accounting.categories.acctg_cath_id 和 b.accounting.categories.acctg_cath_id。但这对我不起作用。
  • 你得到了什么输出,你想得到什么?
  • @jmelesky 我收到一个错误。我想将acctg_cath_id 分组到parent id 下。错误invalid reference to FROM-clause entry for table "categories"
  • 啊,我明白了。在您的原始查询中,您希望选择 a1.acctg_cath_id, a1.parent 而不是 accounting.categories.acctg_cath_id - 只是命名表是不明确的,因为您在连接的两个不同部分处理它。

标签: sql postgresql


【解决方案1】:

您似乎只想对行进行排序:

select *
from accounting.categorie
order by coalesce(parent, acctg_cath_id), parent nulls first, acctg_cath_id;

结果:

+---------------+--------+-------------+ | acctg_cath_id |家长 |描述 | +---------------+--------+-------------+ | 20 | |费用 | | 1 | 20 |票据 | | 9 | 20 |发票 | | 30 | | | | 88 | 30 | | | 89 | 30 | | +---------------+--------+-------------+

【讨论】:

    【解决方案2】:

    您的语法正在执行交叉连接: FROM accounting.categories a1, accounting.categories a2

    尝试以下方法:

    SELECT
        a2.acctg_cath_id,
        a2.parent
    FROM accounting.categories a1
        JOIN accounting.categories a2 ON (a1.acctg_cath_id = a2.parent)
    ;
    

    检查DBFiddle

    【讨论】:

    • 出现错误:[2019-06-27 22:43:48] [42P01] ERROR: invalid reference to FROM-clause entry for table "categories" [2019-06-27 22:43:48] Hint: Perhaps you meant to reference the table alias "a1". [2019-06-27 22:43:48] Position: 13
    • 我已经更新了答案。您收到交叉引用错误的原因是SELECT 子句中列名的语法。在您抛出错误的示例中:<database>.<schema>.<table>.<column>。当您在FROM 子句中应用别名时,您将accounting.categories 分配给别名a1,因此您可以将SELECT 子句中的accounting.categories 替换为a1a2,具体取决于部分您需要的加入。
    • 所以您想要父级及其所有子级?你需要一个递归查询。
    • 我想要父母和孩子。所以我可以稍后在父母 20 岁、孩子 1,9 岁时按以下顺序订购它们。
    • 我添加了一个指向 dbfiddle 的链接,该链接似乎可以提供您正在寻找的结果。您可以在您的问题中添加示例所需的输出吗?或许我可以更深入地了解您正在寻找的结果。
    【解决方案3】:

    你不需要分组,只需要自己加入:

    select 
      c.acctg_cath_id parentid, c.description parent,
      cc.acctg_cath_id childid, cc.description child
    from (
      select distinct parent
      from categories
    ) p inner join categories c
    on p.parent = c.acctg_cath_id
    inner join categories cc on cc.parent = p.parent
    where p.parent = 20
    

    如果您想要所有的父母和他们的孩子,您可以删除 WHERE 子句。
    请参阅demo
    结果:

    > parentid | parent   | childid | child   
    > -------: | :------- | ------: | :-------
    >       20 | Expences |       1 | Bills   
    >       20 | Expences |       9 | Invoices
    

    【讨论】:

      【解决方案4】:

      您不需要自加入。你不需要聚合。你只需要一个group by 子句:

      SELECT ac.*
      FROM accounting.categories ac
      ORDER BY COALESCE(ac.parent, ac.acctg_cath_id),
               (CASE WHEN ac.parent IS NULL THEN 1 ELSE 2 END),
               ac.acctg_cath_id;
      

      【讨论】:

        猜你喜欢
        • 2012-08-08
        • 2011-12-13
        • 2023-02-01
        • 2019-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多