SQL查询可根据键值列表有条件地检索记录

时间:2019-02-10 16:00:36

标签: mysql sql database

我有一个API,该API与具有以下表格的数据库通信:

问题

+----------+------------+
| quest_id | quest_name |
+----------+------------+
|        1 | Q001       |
|        2 | Q002       |
|        3 | Q003       |
|        4 | Q004       |
|        5 | Q005       |
+----------+------------+

技能

+----------+------------+
| skill_id | skill_name |
+----------+------------+
|        1 | S001       |
|        2 | S002       |
|        3 | S003       |
|        4 | S004       |
|        5 | S005       |
+----------+------------+

SKILL_PREREQUISITES

+----------+-----------------------+-------------+
| quest_id | prerequisite_skill_id | skill_value |
+----------+-----------------------+-------------+
|        1 |                     2 |          50 |
|        1 |                     1 |          45 |
|        4 |                     2 |          25 |
|        4 |                     3 |          60 |
|        5 |                     4 |          50 |
+----------+-----------------------+-------------+

任务与游戏中的关卡相对应,并且技能是玩家在玩游戏时获得的。 SKILL_PREREQUISITE表保留了玩家能够参与任务之前需要满足的技能先决条件。

问题

API的端点会接收玩家拥有的技能列表,以及相应技能的技能等级(skill_value),如下所示:

[
{
  "key": 1, //skill ID
  "value": 45 //skill value
},
{
  "key": 2,
  "value": 60
}
...
]

现在我的用例是,以便使用这些值并查询数据库,以根据skill_id和{{ 1}}

示例

假设该API收到以下技能技能值映射:

skill_value

基于此,具有上述技能的玩家可以参加任务1和5,但不能参加任务4,因为4要求技能3得60分。

尝试解决方案

我已经设法编写了一个查询(由于我之前发布了一个问题!),以标识与技能ID对应的任务,但是我不知道如何根据技能值在查询中进一步过滤此查询。

我想知道这是否可能,并且是否可能需要在服务器上进行进一步处理才能获得所需的结果。

为我的解决方案做准备:https://www.db-fiddle.com/f/s2umHS1wz3Q8ibwUhKDas6/1

2 个答案:

答案 0 :(得分:2)

这里的挑战是,您需要将从API响应中检索到的这些值作为输入传递给SQL语句,并通过基于输入动态创建不进行比较的方式来生成输出。

现在,如果我比后端平台更熟悉,我会提供更多合适的解决方案,但是由于我不了解Node.js,我的解决方案将仅包含必需的SQL语句和其余部分你需要DIY。

您需要做的第一件事是解析此API响应并将这些值存储到数据结构中。

现在,从Temporary table代码创建一个Node.js,并将这些输入值存储在此表中。

  CREATE TEMPORARY TABLE Input (id INT, value INT);

将数据结构中的数据添加到此表中。

现在,运行以下查询,您将获得所需的内容:

SELECT skp.quest_id
FROM SKILL_PREREQUISITES skp 
GROUP BY quest_id
HAVING COUNT(skp.quest_id) =
                     ( SELECT COUNT(quest_id)
                       FROM Input i
                       JOIN SKILL_PREREQUISITES sp
                       ON sp.prerequisite_skill_id = i.id
                       AND sp.skill_value <= i.value
                       WHERE skp.quest_id = sp.quest_id
                      )

Demo Fiddle

答案 1 :(得分:1)

您可以通过比较技能和值来用词组查询:

SELECT q.quest_id
FROM QUESTS q LEFT JOIN
     SKILL_PREREQUISITES p
     ON p.quest_id = q.quest_id
GROUP BY q.quest_id
HAVING SUM( p.prerequisite_skill_id = 1 and 50 >= p.skill_value) > 0 AND
       SUM( p.prerequisite_skill_id = 2 and 60 >= p.skill_value) > 0 AND
       SUM( p.prerequisite_skill_id = 4 and 50 >= p.skill_value) > 0 ;

由于您需要具有先决条件的任务,因此不需要LEFT JOIN。实际上,根本不需要JOIN

SELECT p.quest_id
FROM SKILL_PREREQUISITES p
WHERE p.prerequisite_skill_id IN (1, 2, 4)
GROUP BY p.quest_id
HAVING SUM( p.prerequisite_skill_id = 1 and 50 >= p.skill_value) > 0 AND
       SUM( p.prerequisite_skill_id = 2 and 60 >= p.skill_value) > 0 AND
       SUM( p.prerequisite_skill_id = 4 and 50 >= p.skill_value) > 0 ;

GROUP BY之前的过滤是可选的,但可以提高性能。

编辑:

我认为我回答了上面的错误问题。我认为您希望根据用户的先决条件获得所有可用的技能。那应该是:

SELECT q.quest_id
FROM QUESTS q LEFT JOIN
     SKILL_PREREQUISITES p
     ON p.quest_id = q.quest_id
GROUP BY q.quest_id
HAVING COALESCE(SUM( (p.prerequisite_skill_id = 1 and 50 >= p.skill_value) +
                     (p.prerequisite_skill_id = 2 and 60 >= p.skill_value) +
                     (p.prerequisite_skill_id = 4 and 50 >= p.skill_value)
                   )) = COUNT(p.prerequisite_skill_id);