【问题标题】:Relationalship design in PostgreSQLPostgreSQL 中的关系设计
【发布时间】:2015-12-25 09:00:55
【问题描述】:

我正在使用 PostgreSQL,我在我的数据库中创建了 statements 表并插入了以下代码相关的信息:

cur.execute("CREATE TABLE IF NOT EXISTS statements (statement_id SERIAL NOT NULL PRIMARY KEY, statement_name VARCHAR(255) NOT NULL, code INT NOT NULL, FOREIGN KEY (code) REFERENCES companies_list (code))")

statement_name = ["balance_sheet", "income_statement", "cash_flow"]

执行后它给了我以下结果:

 statement_id |  statement_name  | code 
--------------+------------------+---------
        1     | balance_sheet    |    1111
        2     | Income_statement |    1111
        3     | cash_flow        |    1111
        4     | balance_sheet    |    2222

我为每个公司代码启动了 3 个语句。表中的公司代码是完整列表,其中一些代码(在银行部门)需要仅对银行使用不同的报表(资产负债表“银行”、损益表“银行”和现金流量“银行”)。 最好的解决方案是什么?..我需要制作更多报表名称(即 balance_sheets_banks )还是应该将所有这些银行代码包含在列表中并分配一些方法?要么回答我该怎么做?

我问这个问题的原因是在后面的步骤中我正在创建一个表(名为 statement_items )它将包含每个语句的项目,在下面找到它:

cur.execute("CREATE TABLE IF NOT EXISTS statement_items (statement_row_id SERIAL NOT NULL PRIMARY KEY, statement_id INT NOT NULL, row_order INT NOT NULL, row_title VARCHAR(255) NOT NULL, FOREIGN KEY (statement_id) REFERENCES statements (statement_id))")

执行后它会给我:

  statement_row_id | statement_id | row_order |   row_title 
 ------------------+--------------+-----------+----------------
         1         |       1      |     1     | Current Assets
         2         |       2      |     1     |      Sales

那么到底上面第一点怎么解决,下一张表的变化怎么实现呢?

【问题讨论】:

    标签: python postgresql relational-database


    【解决方案1】:

    如果我理解了这个问题,您正在创建一个财务报表表,并且想知道您是否应该将“银行”报表与其他报表一样对待,或者将其视为某些其他报表类型的“特例”。

    根据我的经验,“特殊情况”处理在维护中增加了一层复杂性和难度,这很少是合理的,因此作为一名经验丰富的维护程序员,我的直觉是尽可能避免特殊情况。我只需为“资产负债表”和“资产负债表(银行)”等创建单独的记录。等等。

    我对你问题的第二部分不太清楚,但无论如何我都会试一试,如果我偏离了轨道,你可以纠正我:在没有相互矛盾的要求的情况下,我会给出每个陈述它自己的一组行项目,独立于其他报表上的行项目,就像一张发票的行项目独立于其他发票的行项目一样。可能如有必要在语句之间共享行项目,但在尝试之前我需要看到一个令人信服的用例。

    【讨论】:

      【解决方案2】:

      显然,语句名称是语句格式的名称。银行有银行式的报表。非银行有非银行式的报表。有什么不对称的情况吗?是否需要参数化任何一种表明银行或非银行结构不同的声明?如果没有,只需在银行和非银行中使用对帐单名称:

      Company(company_code, ...)
          PK (company_code)
      Statement(statement_name, company_code, ...)
          PK (statement_name, company_code)
          FK (company_code) to Company)
      Row(statement_name, company_code, row_number, ...)
          PK (statement_name, company_code, row_number)
          FK (company_code) to Company)
          FK(statement_name) to Statement)
      

      酌情将银行和非银行对账单分配给银行和非银行。由于数据库实际上并没有区分银行与非银行,因此没有任何冗余或可能的不一致。 (只是 DBMS - 为给定类型的公司分配了无法检测到的不适当的语句分配。)

      但是,如果您想按公司类型(银行与非银行或其他)参数化公司和报表查询,请将公司类型与公司和报表相关联:

      Company(company_code, company_type, ...)
          PK (company_code)
          UNIQUE NOT NULL (company_code, company_type)
      Statement(statement_name, company_code, company_type, ...)
          PK (statement_name, company_code, company_type)
          FK (company_code, company_type) to Company
      Row(statement_name, company_type, row_number, ...)
          PK (statement_name, company_type, row_number)
          FK(statement_name, company_type) to Statement
      

      声明必须在公司类型上与其公司一致。执行此操作的一种简单方法是在 company_code 和 company_type 上从 Statement 到 Company 的 FK。然后 SQL 要求将每个 FK 目标声明为 PK 或 UNIQUE NOT NULL。我们可以通过名称和公司类型来识别报表。

      就数据库而言,在任一设计中都不需要额外的 CK/PK 代理 id 列。您可以添加它们;但是,如果您在其他基表中使用 id 值而不附带它们各自的自然键值,则可能很难知道是否或如何使用其他 id 约束它们。

      重新寻找合适的设计见this recent answer

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-18
        • 2011-07-24
        • 2019-07-18
        • 2012-04-02
        • 1970-01-01
        • 1970-01-01
        • 2021-11-16
        • 2011-08-02
        相关资源
        最近更新 更多