【问题标题】:Implementing hierarchical structure in sqlite在 sqlite 中实现层次结构
【发布时间】:2019-04-14 18:50:47
【问题描述】:

我是 SQL 的初学者,我正在使用 SQLite 编写 C# 应用程序。我需要帮助在我的数据库中实现https://imgur.com/a/NImUPCc 中显示的层次结构。我知道对于私人帐户,它将是名为 PrivateAccounts 的表(应该将其称为 PersonalAccounts 不是私人的,但现在没那么重要),在那里我会抛出许多带有 ID、登录名等的行。但是怎么做它与公司帐户,哪里有公司的一般帐户,我需要将在该公司工作的人的帐户链接到该帐户?为每家公司创建表是否有效?但这会在数据库中造成很大的混乱,因为如果可能的话,我希望为公司帐户和个人帐户提供一个数据库

【问题讨论】:

  • 您会想了解一对多关系以及如何在数据库中描述这种关系。正如发布的那样,这对于 SO 来说太宽泛了
  • 你还需要学习database normalization
  • 为每个帐户创建一个表不是是有效的(也不是有效的),不建议您必须为个人、企业、私人或其他任何帐户。它是什么类型的帐户可以通过表格上的类型限定符来描述

标签: c# sql sqlite


【解决方案1】:

我建议 3 张桌子。

一个实体表,其中包含帐户所有者的详细信息(并使用对拥有实体的引用来满足子公司的需求),并具有用于类型(私人或公司)的列。

具有帐户名称和所有者的帐户表。

用于记录交易的Account Transaction表,基本上是两列,一列引用账户(因此实体)和交易金额。

以上内容非常简单,您可能希望添加更多列。

示例

以下是一个简短的演示,最终以帐户名称、直接所有者名称和显示的帐户类型显示帐户余额。

DROP TABLE IF EXISTS entity;
DROP TABLE IF EXISTS account;
DROP TABLE IF EXISTS account_transaction;
CREATE TABLE IF NOT EXISTS entity (id INTEGER PRIMARY KEY, entity_name TEXT, entity_type INTEGER, entity_owning_entity);
CREATE TABLE IF NOT EXISTS account (id INTEGER PRIMARY KEY, account_name TEXT, entity_reference INTEGER);
CREATE TABLE IF NOT EXISTS account_transaction (id INTEGER PRIMARY KEY, account_reference INTEGER, amount REAL);
INSERT INTO entity (entity_name, entity_type, entity_owning_entity)
    VALUES
        ("Company 1",1,null), -- will be id 1 
        ("Company 2",1, null), -- will be id 2
      ("Sub Company A",1,1), -- Owned by Company 1 will be id 3
        ("Sub Company B",1,1), -- Owned by Company 1 will be id 4
        ("Sub Company X",1,2), -- Owned by Company 2 will be id 5
        ("Sub Company Y",1,2), -- Owned by Company 2 will be id 6
        ("Fred",0,null), -- Not owned personal type (0) will be id 7
        ("Mary",0,null) -- Not owned, personal type, will be id 8
;
INSERT INTO account (account_name, entity_reference)
    VALUES
        ("Fred's Cheque",7), -- id 1
        ("Sub A Cheque",3), -- id 2
        ("Fred's Savings",7), -- id 3
        ("Mary's Cheque",8), -- id 4
      ("Sub X Chequ",5) -- id 5
;

INSERT INTO account_transaction (account_reference, amount)
    VALUES
        (3,123.45),(3,57.55),(3,200), -- 381 for Fred's Cheque (i.e. references id 3 in the account table)
        (2,100),(2,100),(2,100),(2,100), -- 400 for Sub A Cheque (i.e. references id 2)
        (1,10),
        (4,15),(4,15),(4,30),
        (5,13),(5,14),(5,15),(5,16),(5,17)
;

WITH cte1(id,name) AS 
  -- Use Common Table Expression (temp table) to resolve owner of an entity
    (SELECT id, (SELECT entity_name FROM entity WHERE me.entity_owning_entity = id) FROM entity AS me)

-- Main SELECT Query
SELECT
  -- Handle case when no entity owner or when entity owner
  CASE
        WHEN (SELECT name FROM cte1 where cte1.id = entity.id) IS NULL 
            THEN entity_name
            ELSE (SELECT name FROM cte1 where cte1.id = entity.id)||'-'||entity_name
    END AS AccountOwner,
    account_name AS Account, -- Show the axccount_name
    sum(amount) AS Balance,  -- Show the balance
    -- Use and appropriate value for the type (private or company account)
    CASE
            WHEN entity_type = 1 THEN 'Company'
            WHEN entity_type = 0 THEN 'Private'
        END AS Type
FROM account_transaction -- main table
    JOIN account ON account.id = account_reference -- relationship to the account table
    JOIN entity ON entity.id = entity_reference -- relationship to the entity table
GROUP BY account.id -- group according to accounts (i.e. 1 row is made from all rows in a group for aggregates such a sum)
ORDER BY AccountOwner -- Order result according to the Account Owner 
;

结果

SELECT 查询将返回:-

  • 请注意,您通常不会假设 id 是特定值,为了简洁起见,使用了它们的假设。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-06
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多