javascript - 配方/ Material list MySQL 查询

标签 javascript mysql node.js database

我正在使用 Node.js、Express、React 和 MySQL 为 Minecraft 编写 Material list /配方应用程序。

我拥有我认为带有表的数据库的良好结构,但我遇到了需要运行的查询的问题。这是我尝试使用示例输出执行的操作的示例(我知道配方不是正确的 MC 播放器)。

成分表:

RECIPE        || INGREDIENT   || QTY || TYPE
Piston        || Redstone     ||  1  || RM
Piston        || Iron Ingot   ||  1  || RM
Piston        || Wood Planks  ||  3  || RM
Piston        || Stone        ||  4  || RM
Sticky Piston || Piston       ||  2  || CO
Sticky Piston || Slimeball    ||  1  || RM

我想要的是,当我查询粘性活塞时,会返回一个表,其中将所有必需的组件汇总在一起(在顶部),并将所有必需的原 Material 汇总在一起(在下面)。

表格格式或 JSON 格式所需的输出示例:

INGREDIENT   || QTY || TYPE
Piston       ||  2  || CO
Redstone     ||  2  || RM
Iron Ingot   ||  2  || RM
Wood Planks  ||  6  || RM
Stone        ||  8  || RM
Slimeball    ||  1  || RM


[
    {
        "Ingredient": "Piston",
        "Qty": 2,
        "Type": CO
    },
    {
        "Ingredient": "Redstone",
        "Qty": 2,
        "Type": RM
    },
    {
        "Ingredient": "Iron Ingot",
        "Qty": 2,
        "Type": RM
    },
    {
        "Ingredient": "Wood Planks",
        "Qty": 6,
        "Type": RM
    },
    {
        "Ingredient": "Stone",
        "Qty": 8,
        "Type": RM
    },
    {
        "Ingredient": "Slimeball",
        "Qty": 2,
        "Type": RM
    }
]

我认为它是与其他一些奇特的东西的 JOIN,可以在 MYSQL 语法内完成这一切,但尽管尝试了两天不同的组合,我还是无法弄清楚。

或者,如果我不使用 MYSQL 语法,而是使用可以在 Node.js 服务器上运行的 JS,那就没问题了。

这是根据下面的说明修改的架构版本。这就是我对这种关系的理解应该是这样的,但是当配方由也需要其他 Material 的其他组件组成时,我仍然无法弄清楚如何返回所有所需的资源。

CREATE TABLE Ingredients
(
  MaterialID    INT unsigned NOT NULL AUTO_INCREMENT,
  Material      VARCHAR(250) NOT NULL,
  MaterialImage VARCHAR(250),
  PRIMARY KEY (MaterialID)
);

CREATE TABLE Recipes
(
  RecipeID      INT unsigned NOT NULL AUTO_INCREMENT,
  Recipe        VARCHAR(250) NOT NULL,
  PRIMARY KEY (ComponentID)
);

CREATE TABLE Recipes_Ingredients
(
  RecipeID      INT unsigned NOT NULL,
  MaterialID    INT unsigned NOT NULL,
  Quantity      INT unsigned NOT NULL
)

谢谢!

最佳答案

更新/编辑:

已更新以正确计算数量

我更改了您的表格排列,以更好地匹配您尝试表示的数据。由于“配方”也可以是“ Material ”,因此我删除了配方表,并将该数据存储在 Material 表中。

我还创建了一个 SQL Fiddle,以便您可以使用查询并微调结果。

下面的第一个查询返回所有“食谱”及其组件。要仅获取一个特定配方,只需向选择特定配方的 where 子句添加一个条件即可。

如果您希望在单个字段中列出组件,每个配方一行,您可以使用 GROUP_CONCAT 函数并更改 group by 子句。

下面的第二个查询说明了 GROUP_CONCAT 函数。它还展示了如何将缺少的子成分从 NULL 更改为“无”

SQL Fiddle

MySQL 5.6 架构设置:

CREATE TABLE `Ingredients`
(
  `MaterialID`      INT unsigned NOT NULL AUTO_INCREMENT,
  `Material`        VARCHAR(250) NOT NULL,
  `MaterialImage`   VARCHAR(250),
  `IsRecipe`        TINYINT(1) DEFAULT 0 NULL,
  PRIMARY KEY (`MaterialID`)
);

CREATE TABLE `Recipes_Ingredients`
(
  `id`              INT unsigned NOT NULL AUTO_INCREMENT,
  `RecipeID`        INT unsigned NOT NULL,
  `MaterialID`      INT unsigned NOT NULL,
  `Quantity`        INT unsigned NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO `Ingredients`
(`MaterialID`,`Material`,`MaterialImage`,`IsRecipe`)
VALUES
(1,'Redstone','redstone.jpg',0),
(2,'Iron Ingot','ironingot.jpg',0),
(3,'Wood Planks','woodplanks.jpg',0),
(4,'Stone','stone.jpg',0),
(5,'Slimeball','slimeball.jpg',0),
(6,'Piston','piston.jpg',1),
(7,'Sticky Piston','stickypiston.jpg',1),
(8,'Sticky Piston 2','stickypiston2.jpg',1);


INSERT INTO `Recipes_Ingredients`
(`RecipeID`,`MaterialID`,`Quantity`)
VALUES
(6,1,1),
(6,2,1),
(6,3,3),
(6,4,4),
(7,6,1),
(7,5,1),
(8,6,2),
(8,5,1);

查询 1:

SELECT
  a.`MaterialID`,
  c.`MaterialID`,
  a.`Material` as `Recipe`,
  a.`MaterialImage` as `RecipeImage`,
  c.`Material` as `Ingredient`,
  b.`Quantity` as `FirstIngredientQuantity`,
  c.`MaterialImage` as `IngredientImage`,
  IF(d.`Quantity` IS NULL,SUM(b.`Quantity`),COALESCE(d.`Quantity`,0)*b.`Quantity`) as `Quantity`,
  e.`Material` as `Ingredient`,
  e.`MaterialImage` as `MaterialImage`
FROM `Ingredients` a
LEFT JOIN `Recipes_Ingredients` b
ON b.`RecipeID` = a.`MaterialID`
LEFT JOIN `Ingredients` c
ON c.`MaterialID` = b.`MaterialID`
LEFT JOIN `Recipes_Ingredients` d
ON d.`RecipeID` = c.`MaterialID`
LEFT JOIN `Ingredients` e
ON e.`MaterialID` = d.`MaterialID` AND c.`IsRecipe` = 1
WHERE a.`IsRecipe` = 1 AND a.`MaterialID` in (7,8)
GROUP BY a.`MaterialID`,c.`MaterialID`,e.`MaterialID`

<强> Results :

| MaterialID | MaterialID |          Recipe |       RecipeImage | Ingredient | FirstIngredientQuantity | IngredientImage | Quantity |  Ingredient |  MaterialImage |
|------------|------------|-----------------|-------------------|------------|-------------------------|-----------------|----------|-------------|----------------|
|          7 |          5 |   Sticky Piston |  stickypiston.jpg |  Slimeball |                       1 |   slimeball.jpg |        1 |      (null) |         (null) |
|          7 |          6 |   Sticky Piston |  stickypiston.jpg |     Piston |                       1 |      piston.jpg |        1 |    Redstone |   redstone.jpg |
|          7 |          6 |   Sticky Piston |  stickypiston.jpg |     Piston |                       1 |      piston.jpg |        1 |  Iron Ingot |  ironingot.jpg |
|          7 |          6 |   Sticky Piston |  stickypiston.jpg |     Piston |                       1 |      piston.jpg |        3 | Wood Planks | woodplanks.jpg |
|          7 |          6 |   Sticky Piston |  stickypiston.jpg |     Piston |                       1 |      piston.jpg |        4 |       Stone |      stone.jpg |
|          8 |          5 | Sticky Piston 2 | stickypiston2.jpg |  Slimeball |                       1 |   slimeball.jpg |        1 |      (null) |         (null) |
|          8 |          6 | Sticky Piston 2 | stickypiston2.jpg |     Piston |                       2 |      piston.jpg |        2 |    Redstone |   redstone.jpg |
|          8 |          6 | Sticky Piston 2 | stickypiston2.jpg |     Piston |                       2 |      piston.jpg |        2 |  Iron Ingot |  ironingot.jpg |
|          8 |          6 | Sticky Piston 2 | stickypiston2.jpg |     Piston |                       2 |      piston.jpg |        6 | Wood Planks | woodplanks.jpg |
|          8 |          6 | Sticky Piston 2 | stickypiston2.jpg |     Piston |                       2 |      piston.jpg |        8 |       Stone |      stone.jpg |

查询 2:

SELECT
  a.`MaterialID`,
  c.`MaterialID`,
  a.`Material` as `Recipe`,
  a.`MaterialImage` as `RecipeImage`,
  c.`Material` as `Ingredient`,
  c.`MaterialImage` as `MaterialImage`,
  SUM(b.`Quantity` + COALESCE(d.`Quantity`,0)) as `Quantity`,
  COALESCE(GROUP_CONCAT(CONCAT(e.`Material`,' (',b.`Quantity` * d.`Quantity`,') [',e.`MaterialImage`,']')),'None') as `Ingredients`
FROM `Ingredients` a
LEFT JOIN `Recipes_Ingredients` b
ON b.`RecipeID` = a.`MaterialID`
LEFT JOIN `Ingredients` c
ON c.`MaterialID` = b.`MaterialID`
LEFT JOIN `Recipes_Ingredients` d
ON d.`RecipeID` = c.`MaterialID`
LEFT JOIN `Ingredients` e
ON e.`MaterialID` = d.`MaterialID` AND c.`IsRecipe` = 1
WHERE a.`IsRecipe` = 1
GROUP BY a.`MaterialID`,c.`MaterialID`

<强> Results :

| MaterialID | MaterialID |          Recipe |       RecipeImage |  Ingredient |  MaterialImage | Quantity |                                                                                                       Ingredients |
|------------|------------|-----------------|-------------------|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------|
|          6 |          1 |          Piston |        piston.jpg |    Redstone |   redstone.jpg |        1 |                                                                                                              None |
|          6 |          2 |          Piston |        piston.jpg |  Iron Ingot |  ironingot.jpg |        1 |                                                                                                              None |
|          6 |          3 |          Piston |        piston.jpg | Wood Planks | woodplanks.jpg |        3 |                                                                                                              None |
|          6 |          4 |          Piston |        piston.jpg |       Stone |      stone.jpg |        4 |                                                                                                              None |
|          7 |          5 |   Sticky Piston |  stickypiston.jpg |   Slimeball |  slimeball.jpg |        1 |                                                                                                              None |
|          7 |          6 |   Sticky Piston |  stickypiston.jpg |      Piston |     piston.jpg |       13 | Redstone (1) [redstone.jpg],Iron Ingot (1) [ironingot.jpg],Wood Planks (3) [woodplanks.jpg],Stone (4) [stone.jpg] |
|          8 |          5 | Sticky Piston 2 | stickypiston2.jpg |   Slimeball |  slimeball.jpg |        1 |                                                                                                              None |
|          8 |          6 | Sticky Piston 2 | stickypiston2.jpg |      Piston |     piston.jpg |       17 | Redstone (2) [redstone.jpg],Iron Ingot (2) [ironingot.jpg],Wood Planks (6) [woodplanks.jpg],Stone (8) [stone.jpg] |

关于javascript - 配方/ Material list MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51117420/

相关文章:

javascript - backbone.validation 与 brunch.io 集成(backbone.js 框架)

javascript - 有没有办法在单击时将一个 div 的文本放入另一个 div 中?

php - 如何统计数据库中meta_value的使用次数

node.js - 多语言微服务方法

javascript - 使用 Multer 更改上传文件的目的地

javascript - 使用 jquery 将我的内容加载到 div 后如何获得单独的链接?

javascript - 刷卡器 : second instance of swiper not initializing

mysql - 累计数字永不减少

php - 学说查询生成器从不是实体表的表中选择

javascript - 如何将数据从一个函数传递到作为第一个函数的参数的另一个函数