【问题标题】:Mysql technique for Skill dependencies技能依赖的Mysql技术
【发布时间】:2012-05-03 12:25:05
【问题描述】:

我有一个关于存储依赖项的数据库技术的问题。我知道那里有很多,但我不能轻易地将它们放在我需要的方案中。 我创建了简单的图像:

如您所见,我需要创建一个相互依赖的技能树(就像在游戏中一样)。因此,例如,如果有人想要拥有技能 8,我可以告诉他他需要先拥有技能 1,2 和 5。

这对于数据库中的分层数据可能很好,但我不太清楚如何动态地执行此模型。我遇到的问题是,技能将一直添加到树中所有可能的位置。没完没了。可以在任何级别添加技能。

在第一个问题之后,还有一个复杂的问题。我也需要有水平的技能。因此,例如技能 1 可以有 10 个级别。并且只有达到技能1的5级才能达到技能2。

对于玩魔兽世界这类游戏的人来说应该是可以理解的。

再注意一点,技能可以随时添加,但是添加后不能更改。在正常的基础上。以防万一某些技能非常糟糕或类似的情况,则将其删除,但这种情况很少发生。

感谢您的建议、链接或任何其他材料!

【问题讨论】:

  • 如果没有某种存储过程来处理循环并递归地尝试添加所有符合条件的内容,则无法在单个查询中完成,因为您已经注意到您永远不知道有多少层深数据将继续。
  • 它不必在单个查询中完成,我只需要一些技术来实现这一点
  • MySQL 是必需的吗?这在支持 CTE 和窗口功能的数据库上很容易stackoverflow.com/a/10395130stackoverflow.com/a/10401572 现场测试:sqlfiddle.com/#!1/db290/85
  • 是的 MySQL 是必需的,但是您发布的链接看起来非常适合这个问题。
  • 在你的图表上,7 需要技能 #6。但在您的表格结果中,不包括 6

标签: php mysql database


【解决方案1】:

我面临足够的挑战来解决问题,但我没有足够的挑战来解决 MySQL 中的问题。考虑到这一点,这是您的问题的 Postgresql 版本:

with recursive 
skill_list(skill_id) as
(
    select distinct skill_id from skill_req 
    where req is not null
    union
    select distinct req from skill_req
    where req is not null 
)
,skill_tree(skill_group, depend_on) as
(
    select skill_id, skill_id -- seeds
    from skill_list         
    union       
    select st.skill_group, sr.req
    from skill_req sr
    join skill_tree st 
    on sr.skill_id = st.depend_on 
)
,skills_required as
(
    select skill_group, depend_on
    from skill_tree
    where skill_group <> depend_on -- remove seeds  
)
select 
    sl.skill_id, 
    array_agg(sr.depend_on order by depend_on) as array_version,
    array_to_string(array_agg(sr.depend_on order by depend_on), ',') 
        as group_concat_version    
from skill_list sl
left join skills_required sr on sr.skill_group = sl.skill_id
group by sl.skill_id  

数据:

CREATE TABLE skill_req
    (skill_id int, req int);

INSERT INTO skill_req
    (skill_id, req)
VALUES   
   (2, 1),

   (4, 3),

   (5, 1),

   (6, 4), 
   (6, 2),

   (7, 6),   
   (7, 9),

   (8, 2),
   (8, 5),

   (9, 3),

   (10, 4),
   (10, 5),
   (10, 9);

输出:

 skill_id | array_version | group_concat_version 
----------+---------------+----------------------
        1 | {NULL}        | 
        2 | {1}           | 1
        3 | {NULL}        | 
        4 | {3}           | 3
        5 | {1}           | 1
        6 | {1,2,3,4}     | 1,2,3,4
        7 | {1,2,3,4,6,9} | 1,2,3,4,6,9
        8 | {1,2,5}       | 1,2,5
        9 | {3}           | 3
       10 | {1,3,4,5,9}   | 1,3,4,5,9
(10 rows)

现场测试:http://www.sqlfiddle.com/#!1/77894/1

【讨论】:

  • 除了查询之外,其相关性还有待商榷,尤其是它不适用于 MySQL。设计就在那里,这怎么可能无关紧要? :-) 如果我要创建一个技能图,那将是我的数据库设计,只有两个字段,以保持概念模型的简单。与技能相关的其他辅助信息将保存在单独的表格中。
【解决方案2】:

如您所见,我需要创建一个技能树(例如 游戏),它们相互依赖。

我也需要技能才能达到等级。所以例如技能1可以 有 10 个级别。

这意味着你需要一个表格来存储技能和技能的最高等级,基本上:

create table skills(
  skill_id integer,
  skill_name varchar(500) not null,
  skill_max_level integer not null,
  primary key(skill_id));

并且您需要使用所需的可选级别来设置依赖:

create table skills_depend
( skill_id integer
, skill_depend integer
, level_depend integer 
, primary key(skill_id, skill_depend)
, foreign key (skill_id)
  references skills (skill_id)
, foreign key (skill_depend)
  references skills (skill_id) );

查询将取决于您要检查的内容(例如,用户是否具备获得技能的先决条件)。

将此与用户级别和他已经拥有的技能相结合,我认为这是一个起点。

再补充一点,技能可以随时添加,但不能更改 添加后。在正常的基础上。以防万一有些技能是 非常糟糕或类似的东西,那么它将被删除,但是 这种情况很少发生。

您需要在应用程序级别控制此要求(让用户只添加或删除技能)。


你可以在SQLFiddle上玩这个

【讨论】:

  • 你能告诉我示例查询以获得我在图片上的技能树吗?让我们说技能 7,谢谢
  • 嗯,MySQL 不支持递归查询。您需要使用 PHP 来执行此操作。
  • 但在这种情况下,我认为这会大大减慢项目的速度。我还是觉得应该有办法。例如,如果您查看hirearchial 数据结构(它在此处的某处),您可以在其中保留左右的数字,则可以获得整个树。但我只是似乎不适合这个理论来满足我的需求
  • “大大减慢了项目的速度”:你是如何基于这个想法的?
  • 好吧,假设我有一个技能,要求有 10 个技能,它们都是递归级别。所以我会得到所需的技能和所有最近的所需技能。然后对于所有这些,我再次获得查询以获取最近的技能等。所以最后我可能会调用数百个查询。请分享其他想法
猜你喜欢
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 2015-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
相关资源
最近更新 更多