精华内容
下载资源
问答
  • 关于多级分销的数据库设计

    千次阅读 2019-10-31 16:32:00
    https://blog.csdn.net/cctcc/article/details/53992215#commentBox 多级分销的情况下,不限制层级可以直接加一个冗余字段

    https://blog.csdn.net/cctcc/article/details/53992215#commentBox

    多级分销的情况下,不限制层级可以直接加一个冗余字段

    展开全文
  • 1. 数据库设计的原则 1) 准确记录账户基本信息,特别是状态。 2) 交易时要正确记录下交易信息和账户状态。 3) 交易记录是历史性的,不可篡改。 4) 交易是连续的,对时间要求准确。 5) 交易...
    1. 数据库设计的原则

    1) 准确记录账户基本信息,特别是状态。

    2) 交易时要正确记录下交易信息和账户状态。

    3) 交易记录是历史性的,不可篡改。

    4) 交易是连续的,对时间要求准确。

    5) 交易记录要完整,对安全性有要求。


    2.主要数据表

    1) 账户基本信息表

        记录账户的持有人姓名、联络方式、余额、有效期、密码、流通范围等。为了安全,该表还应该由账户、姓名、有效期和余额组成的检验串,防止有人恶意修改余额或账号。

    2) 交易记录表

        记录每一笔交易信息,除了记录交易账户、交易时间、交易金额、交易后余额和交易内容(充值或消费购物)外,还应该记录下账户的其它基本信息,如账户持有人姓名、交易地点等。这也许会增加数据的存储量,但这是有必要的。如在银行储藏点存下钱,这个储藏点若干年后,可能更名、关闭等,在此之后要查当初在这个点的交易时,就可能会用到初交易时的信息。

         另外,交易记录不建立使用太多的代码表示特定意思,一是时间太久了会看不明白代码是什么意思,二是代码可能被重复使用。

         所有交易必须有数据完整性校验,即一行记录一旦生成后其校验串也就固定了,防止有人恶意修改记录行的值。

    3) 账户变更记录表

        由于账户基本信息是可变更的,基于交易系统的交易记录的历史性和档案性,所以对账户基本信息的任何变更都必须有记录,由什么变更为什么,一定要有记录,否则以后一旦查历史,找不到当初变更的信息就麻烦了。

    4) 操作日志明细表

        所有的操作必须有详细的日志记录。

    3.技巧

    1) 应当根据应该的规模进行合理设计,如交易量非常大(每天超过10万笔)那就需要考虑创建分区表,如果更大,就要考虑建立历史交易表或交易库,即把一年或几年前的数据独立出来,仅供特殊需要时查询。

    2) 建立索引,如按日期、账户建立索引,可以加快查询速度。

    3) 建立报表数据存储表,即在报表生成之后,就把生成的结果数据保存下来,以后再要进直接进行查询,不要每次都根据原始表进行统计。

    4) 适当提高硬件配置是比较划算的。

    4.其它

    1) 一定要考虑扩展性,主要在应用地区范围、时间范围、用户(消费者)、客户(商家)方面。

    2) 应急的处理,如备份、分布式(不同地方设立数据库)的独立运行、离线等。

    3) 要有开放的思想,想想在未来如何方便其它系统、成员、合作伙伴也可以加入进来。

    5、图片描述

    展开全文
  • 多级分销系统数据库模型(猜想)

    千次阅读 2016-09-01 01:22:17
    需求:假设现在有一个九级分销商城项目,每个用户下面的九级下线买东西都可以给这个人带来分润收益。并且每一级的分润比例都不同,可能下面第一级分润比例是10%,第二级分润比例是5%,........。如何存储所有用户...

    需求:假设现在有一个九级分销商城项目,每个用户下面的九级下线买东西都可以给这个人带来分润收益。并且每一级的分润比例都不同,可能下面第一级分润比例是10%,第二级分润比例是5%,........。如何存储所有用户信息才能更好管理数据以及方便计算某一个用户的分成。

    猜想1:用NoSQL(比如MongoDB)数据库以树型结构存储用户ID和用户金额。用SQL数据库存储用户ID,以及该用户在树形结构中的内嵌路径。

    当需要计算某一个用户的总分润,先根据用户ID去SQL数据库找出该用户在NoSQL中的内嵌路径,再根据该路径从NoSQL数据库中提取出此路径下的内嵌文档。此时提取出的树型信息表中只有前九级是有用的信息,所以,在内存中提取出前九级金额信息同时就可以计算出所求用户的分成金额。


    猜想2:........

    展开全文
  • mysql(多级分销)无限极数据库设计方法 相信有过开发经验的朋友都曾碰到过这样一个需求。假设你正在为一个新闻网站开发一个评论功能,读者可以评论原文甚至相互回复。 这个需求并不简单,相互回复会导致无限多的...

    mysql(多级分销)无限极数据库设计方法

    相信有过开发经验的朋友都曾碰到过这样一个需求。假设你正在为一个新闻网站开发一个评论功能,读者可以评论原文甚至相互回复。

    这个需求并不简单,相互回复会导致无限多的分支,无限多的祖先-后代关系。这是一种典型的递归关系数据。

    对于这个问题,以下给出几个解决方案,各位客观可斟酌后选择。

    一、邻接表:依赖父节点

      邻接表的方案如下(仅仅说明问题):

    1

    2

    3

    4

    5

    6

    CREATE TABLE Comments(

        CommentId  int  PK,

        ParentId   int,    --记录父节点    ArticleId  int,

        CommentBody nvarchar(500),

        FOREIGN KEY (ParentId)  REFERENCES Comments(CommentId)   --自连接,主键外键都在自己表内    FOREIGN KEY (ArticleId) REFERENCES Articles(ArticleId)

      )

      由于偷懒,所以采用了书本中的图了,Bugs就是Articles:

     

      这种设计方式就叫做邻接表。这可能是存储分层结构数据中最普通的方案了。

      下面给出一些数据来显示一下评论表中的分层结构数据。示例表:

     

    图片说明存储结构:

     

    邻接表的优缺分析

      对于以上邻接表,很多程序员已经将其当成默认的解决方案了,但即便是这样,但它在从前还是有存在的问题的。

      分析1:查询一个节点的所有后代(求子树)怎么查呢?

      我们先看看以前查询两层的数据的SQL语句:

    1

    2

    SELECT c1.*,c2.*  FROM Comments c1 LEFT OUTER JOIN Comments2 c2

      ON c2.ParentId = c1.CommentId

      显然,每需要查多一层,就需要联结多一次表。SQL查询的联结次数是有限的,因此不能无限深的获取所有的后代。而且,这种这样联结,执行Count()这样的聚合函数也相当困难。

      说了是以前了,现在什么时代了,在SQLServer 2005之后,一个公用表表达式就搞定了,顺带解决的还有聚合函数的问题(聚合函数如Count()也能够简单实用),例如查询评论4的所有子节点:

    1

    2

    3

    4

    5

    6

    7

    WITH COMMENT_CTE(CommentId,ParentId,CommentBody,tLevel)AS(    --基本语句

        SELECT CommentId,ParentId,CommentBody,0 AS tLevel FROM Comment    WHERE ParentId = 4

        UNION ALL  --递归语句

        SELECT c.CommentId,c.ParentId,c.CommentBody,ce.tLevel + 1 FROM Comment AS 

        INNER JOIN COMMENT_CTE AS ce    --递归查询

        ON c.ParentId = ce.CommentId

    )SELECT FROM COMMENT_CTE

      显示结果如下:

     

    那么查询祖先节点树又如何查呢?例如查节点6的所有祖先节点:

    1

    2

    3

    4

    5

    6

    WITH COMMENT_CTE(CommentId,ParentId,CommentBody,tLevel)AS(    --基本语句

        SELECT CommentId,ParentId,CommentBody,0 AS tLevel FROM Comment    WHERE CommentId = 6

        UNION ALL

        SELECT c.CommentId,c.ParentId,c.CommentBody,ce.tLevel - 1  FROM Comment AS c 

        INNER JOIN COMMENT_CTE AS ce  --递归查询    ON ce.ParentId = c.CommentId    where ce.CommentId <> ce.ParentId

    )SELECT * FROM COMMENT_CTE ORDER BY CommentId ASC

     结果如下:

     

      再者,由于公用表表达式能够控制递归的深度,因此,你可以简单获得任意层级的子树。

    1

    OPTION(MAXRECURSION 2)

      看来哥是为邻接表平反来的。

     分析2:当然,邻接表也有其优点的,例如要添加一条记录是非常方便的。

    1

    INSERT INTO Comment(ArticleId,ParentId)...    --仅仅需要提供父节点Id就能够添加了。

      分析3:修改一个节点位置或一个子树的位置也是很简单.

    1

    UPDATE Comment SET ParentId = 10 WHERE CommentId = 6  --仅仅修改一个节点的ParentId,其后面的子代节点自动合理。

    分析4:删除子树

      想象一下,如果你删除了一个中间节点,那么该节点的子节点怎么办(它们的父节点是谁),因此如果你要删除一个中间节点,那么不得不查找到所有的后代,先将其删除,然后才能删除该中间节点。

      当然这也能通过一个ON DELETE CASCADE级联删除的外键约束来自动完成这个过程。

      分析5:删除中间节点,并提升子节点

      面对提升子节点,我们要先修改该中间节点的直接子节点的ParentId,然后才能删除该节点:

    1

    SELECT ParentId FROM Comments WHERE CommentId = 6;    --搜索要删除节点的父节点,假设返回4  UPDATE Comments SET ParentId = 4 WHERE ParentId = 6;  --修改该中间节点的子节点的ParentId为要删除中间节点的ParentId  DELETE FROM Comments WHERE CommentId = 6;          --终于可以删除该中间节点了

      由上面的分析可以看到,邻接表基本上已经是很强大的了。

    二、路径枚举

      路径枚举的设计是指通过将所有祖先的信息联合成一个字符串,并保存为每个节点的一个属性。

      路径枚举是一个由连续的直接层级关系组成的完整路径。如"/home/account/login",其中home是account的直接父亲,这也就意味着home是login的祖先。

      还是有刚才新闻评论的例子,我们用路径枚举的方式来代替邻接表的设计:

    1

    2

    3

    4

    5

    6

    CREATE TABLE Comments(

        CommentId  int  PK,

        Path      varchar(100),    --仅仅改变了该字段和删除了外键    ArticleId  int,

        CommentBody nvarchar(500),

        FOREIGN KEY (ArticleId) REFERENCES Articles(ArticleId)

      )

     

       简略说明问题的数据表如下:

    CommentId Path CommentBody

    1 1/        这个Bug的成因是什么

    2 1/2/     我觉得是一个空指针

    3 1/2/3  不是,我查过了

    4 1/4/     我们需要查无效的输入

    5 1/4/5/    是的,那是个问题

    6 1/4/6/    好,查一下吧。

    7 1/4/6/7/   解决了

    路径枚举的优点:

      对于以上表,假设我们需要查询某个节点的全部祖先,SQL语句可以这样写(假设查询7的所有祖先节点):

    1

    SELECT FROM Comment AS cWHERE '1/4/6/7/' LIKE c.path + '%'

      结果如下:

     

      假设我们要查询某个节点的全部后代,假设为4的后代:

    SELECT * FROM Comment AS cWHERE c.Path LIKE '1/4/%'

      结果如下:

     

      一旦我们可以很简单地获取一个子树或者从子孙节点到祖先节点的路径,就可以很简单地实现更多查询,比如计算一个字数所有节点的数量(COUNT聚合函数)

     

       插入一个节点也可以像和使用邻接表一样地简单。可以插入一个叶子节点而不用修改任何其他的行。你所需要做的只是复制一份要插入节点的逻辑上的父亲节点路径,并将这个新节点的Id追加到路径末尾就可以了。如果这个Id是插入时由数据库生成的,你可能需要先插入这条记录,然后获取这条记录的Id,并更新它的路径。

    路径枚举的缺点:

    1、数据库不能确保路径的格式总是正确或者路径中的节点确实存在(中间节点被删除的情况,没外键约束)。

    2、要依赖高级程序来维护路径中的字符串,并且验证字符串的正确性的开销很大。

    3、VARCHAR的长度很难确定。无论VARCHAR的长度设为多大,都存在不能够无限扩展的情况。

      路径枚举的设计方式能够很方便地根据节点的层级排序,因为路径中分隔两边的节点间的距离永远是1,因此通过比较字符串长度就能知道层级的深浅。

    三、嵌套集

      嵌套集解决方案是存储子孙节点的信息,而不是节点的直接祖先。我们使用两个数字来编码每个节点,表示这个信息。可以将这两个数字称为nsleft和nsright。

      还是以上面的新闻-评论作为例子,对于嵌套集的方式表可以设计为:

    1

    2

    3

    4

    5

    6

    7

    CREATE TABLE Comments(

        CommentId  int  PK,

        nsleft    int,  --之前的一个父节点

           nsright   int,  --变成了两个    ArticleId  int,

        CommentBody nvarchar(500),

        FOREIGN KEY (ArticleId) REFERENCES Articles(ArticleId)

      )

    nsleft值的确定:nsleft的数值小于该节点所有后代的Id。

    nsright值的确定:nsright的值大于该节点所有后代的Id。

      当然,以上两个数字和CommentId的值并没有任何关联,确定值的方式是对树进行一次深度优先遍历,在逐层入神的过程中依次递增地分配nsleft的值,并在返回时依次递增地分配nsright的值。

      采用书中的图来说明一下情况:

     

      一旦你为每个节点分配了这些数字,就可以使用它们来找到给定节点的祖先和后代。

    嵌套集的优点:

      我觉得是唯一的优点了,查询祖先树和子树方便。

      例如,通过搜索那些节点的ConmentId在评论4的nsleft与nsright之间就可以获得其及其所有后代:

    1

    2

    SELECT c2.* FROM Comments AS c1   JOIN Comments AS c2  ON cs.neleft BETWEEN c1.nsleft AND c1.nsright

      WHERE c1.CommentId = 1;

      结果如下:

     

      通过搜索评论6的Id在哪些节点的nsleft和nsright范围之间,就可以获取评论6及其所有祖先:

    1

    2

    3

    SELECT c2.* FROM Comment AS c1

      JOIN Comment AS c2 ON c1.nsleft BETWEEN c2.nsleft AND c2.nsright

      WHERE c1.CommentId = 6;

     

      这种嵌套集的设计还有一个优点,就是当你想要删除一个非叶子节点时,它的后代会自动地代替被删除的节点,称为其直接祖先节点的直接后代。

      嵌套集设计并不必须保存分层关系。因此当删除一个节点造成数值不连续时,并不会对树的结构产生任何影响。

      嵌套集缺点:

    1、查询直接父亲。

      在嵌套集的设计中,这个需求的实现的思路是,给定节点c1的直接父亲是这个节点的一个祖先,且这两个节点之间不应该有任何其他的节点,因此,你可以用一个递归的外联结来查询一个节点,它就是c1的祖先,也同时是另一个节点Y的后代,随后我们使y=x就查询,直到查询返回空,即不存在这样的节点,此时y便是c1的直接父亲节点。

      比如,要找到评论6的直接父节点:老实说,SQL语句又长又臭,行肯定是行,但我真的写不动了。

    2、对树进行操作,比如插入和移动节点。

      当插入一个节点时,你需要重新计算新插入节点的相邻兄弟节点、祖先节点和它祖先节点的兄弟,来确保它们的左右值都比这个新节点的左值大。同时,如果这个新节点是一个非叶子节点,你还要检查它的子孙节点。

      够了,够了。就凭查直接父节点都困难,这个东西就很冷门了。我确定我不会使用这种设计了。

    四、闭包表

      闭包表是解决分层存储一个简单而又优雅的解决方案,它记录了表中所有的节点关系,并不仅仅是直接的父子关系。
      在闭包表的设计中,额外创建了一张TreePaths的表(空间换取时间),它包含两列,每一列都是一个指向Comments中的CommentId的外键。

    1

    2

    3

    4

    5

    6

    CREATE TABLE Comments(

      CommentId int PK,

      ArticleId int,

      CommentBody int,

      FOREIGN KEY(ArticleId) REFERENCES Articles(Id)

    )

      父子关系表:

    1

    2

    3

    4

    5

    6

    CREATE TABLE TreePaths(

      ancestor    int,

      descendant int,

      PRIMARY KEY(ancestor,descendant),    --复合主键  FOREIGN KEY (ancestor) REFERENCES Comments(CommentId),

      FOREIGN KEY (descendant) REFERENCES Comments(CommentId)

    )

      在这种设计中,Comments表将不再存储树结构,而是将书中的祖先-后代关系存储为TreePaths的一行,即使这两个节点之间不是直接的父子关系;同时还增加一行指向节点自己,理解不了?就是TreePaths表存储了所有祖先-后代的关系的记录。如下图:

     

    Comment表:

     

    TreePaths表:

     

      优点:

    1、查询所有后代节点(查子树):

    1

    SELECT c.* FROM Comment AS c    INNER JOIN TreePaths t on c.CommentId = t.descendant    WHERE t.ancestor = 4

      结果如下:

     

    2、查询评论6的所有祖先(查祖先树):

    1

    SELECT c.* FROM Comment AS c    INNER JOIN TreePaths t on c.CommentId = t.ancestor    WHERE t.descendant = 6

      显示结果如下:

     

      3、插入新节点:

      要插入一个新的叶子节点,应首先插入一条自己到自己的关系,然后搜索TreePaths表中后代是评论5的节点,增加该节点与要插入的新节点的"祖先-后代"关系。

      比如下面为插入评论5的一个子节点的TreePaths表语句:

    1

    2

    3

    4

    INSERT INTO TreePaths(ancestor,descendant)    SELECT t.ancestor,8

        FROM TreePaths AS t    WHERE t.descendant = 5

        UNION ALL

        SELECT 8,8

      执行以后:

     

      至于Comment表那就简单得不说了。

    4、删除叶子节点:

      比如删除叶子节点7,应删除所有TreePaths表中后代为7的行:

    1

    DELETE FROM TreePaths WHERE descendant = 7

    5、删除子树:

    要删除一颗完整的子树,比如评论4和它的所有后代,可删除所有在TreePaths表中的后代为4的行,以及那些以评论4的后代为后代的行:

    1

    2

    3

    DELETE FROM TreePaths

      WHERE descendant 

      IN(SELECT descendant FROM TreePaths WHERE ancestor = 4)

      另外,移动节点,先断开与原祖先的关系,然后与新节点建立关系的SQL语句都不难写。

      另外,闭包表还可以优化,如增加一个path_length字段,自我引用为0,直接子节点为1,再一下层为2,一次类推,查询直接自子节点就变得很简单。

    总结

      其实,在以往的工作中,曾见过不同类型的设计,邻接表,路径枚举,邻接表路径枚举一起来的都见过。

      每种设计都各有优劣,如果选择设计依赖于应用程序中哪种操作最需要性能上的优化。 

      下面给出一个表格,来展示各种设计的难易程度:

    设计

    表数量

    查询子

    查询树

    插入

    删除

    引用完整性

    邻接表

    1

    简单

    简单

    简单

    简单

    枚举路径

    1

    简单

    简单

    简单

    简单

    嵌套集

    1

    困难

    简单

    困难

    困难

    闭包表

    2

    简单

    简单

    简单

    简单

    1、邻接表是最方便的设计,并且很多软件开发者都了解它。并且在递归查询的帮助下,使得邻接表的查询更加高效。

    2、枚举路径能够很直观地展示出祖先到后代之间的路径,但由于不能确保引用完整性,使得这个设计比较脆弱。枚举路径也使得数据的存储变得冗余。

    3、嵌套集是一个聪明的解决方案,但不能确保引用完整性,并且只能使用于查询性能要求较高,而其他要求一般的场合使用它。

    4、闭包表是最通用的设计,并且最灵活,易扩展,并且一个节点能属于多棵树,能减少冗余的计算时间。但它要求一张额外的表来存储关系,是一个空间换取时间的方案。

     生活中很多人喜欢就一件事左右摇摆,举棋不定。轻易落子怕输了,一子不落怕错过。于是他们一直纠结于细微得不值得一提的小事,让自己始终活在紧张的泥潭不能自拔。在自己短暂的一生中,谨小慎微,防微杜渐,也许别人的一句话,一个眼神,一个表情,都会不断揣摩,我们生活的这个社会本就很复杂,然而很多人把这个本来就复杂的社会弄得更加复杂,复杂的无章可循。贪婪的人容易受到打击。欲望越少,生活越幸福。

    我们的软件开发公司,根据客户的需求做定制,专业开发微商城分销,代理商系统,代理分红,积分商城,购物返系统,全球分红,区域代理等商城分销系统模式,330理财游戏,拼团,资金盘,双轨制公排系统,区块链挖矿技术app定制开发。高经理 137-7356-0781 电/微 (微信同号) 

    展开全文
  • 三级分销系统系统设计

    千次阅读 2019-09-27 17:43:01
    系统角色:货主,各级分销商(定三级),微信用户,购买者 货主可以将自己的商品上架 货主可以设置通用分销比例 货主可以发展一级分销商并设置分销比例(通用分销比例) 货主可以设置...
  • 最近在做一个基于有赞的多级分销管理系统,所有成员的店面均在有赞商城,使用有赞API获得他们的业绩,但是有赞提供的分销只有一级,故制作该系统。考虑到减轻工作量,理清层次关系,采用了OOP设计方法,将数据库,表...
  • 通过Spring Cloud构建PC+微信+APP+云服务的云商平台系统,其中包括B2B、B2C、C2C、O2O、新零售、直播电商等子平台,之前我们讲了很多关于Spring Cloud的概念文章,从本节开始,我们会以分布式微服务电子商务平台为...
  • 消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不...
  • Niushop分销系统佣金算法设计思路

    千次阅读 2019-03-27 10:02:08
    Niushop分销系统佣金算法设计思路 Niushop分销系统当前设置的分销模式一共有4种,分别是三级分销,区域代理,股东分红,全球分红 三级分销: 1.1 系统设置三级分销 系统可以设置对否开启三级分销以及推广员审核...
  • 它提供了普通消息系统的功能,但具有自己独特的设计。这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统术语: Kafka将消息以topic为单位进行归纳。 将向Kafka topic发布消息的程序成为producers. 将...
  • 单点登录SSO(Single Sign-On)是身份管理中的一部分。 SSO的一种较为通俗的定义是:SSO是指访问同一服务器不同...目前的企业应用环境中,往往有很多的应用系统,如办公自动化(OA)系统,财务管理系统,档案管理...
  • Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现。也是springcloud体系中...java B2B2C 源码 多级分销springmvc mybatis多租户电子商城系统

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 403
精华内容 161
关键字:

多级分销系统设计