Рецепт / спецификация MySQL Query

0

Я пишу приложение к материалам/рецепту для Minecraft в Node.js, Express, React и MySQL.

У меня есть то, что я считаю хорошей структурой для базы данных с таблицами, но у меня возникает проблема с запросами, которые мне нужно запустить. Вот пример того, что я пытаюсь сделать с примером вывода (я знаю, что рецепт неправильный 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

Я хочу, чтобы при запросе на Sticky Piston была возвращена таблица со всеми необходимыми компонентами, суммированными вместе (сверху) и всеми необходимыми исходными материалами, суммированными вместе (ниже).

Пример Требуемый вывод в формате таблицы или формате 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
    }
]

Я предполагаю, что это ПРИСОЕДИНИТЕСЬ с некоторыми другими причудливыми вещами, которые могут делать все это внутри синтаксиса MYSQL, но я не могу понять это, несмотря на два дня опробовать разные комбинации.

В качестве альтернативы, было бы замечательно, если бы вместо использования синтаксиса MYSQL этот JS использовался, чтобы я мог запускать его на моем сервере Node.js.

Ниже приведена модифицированная версия схемы по инструкциям ниже. Это то, чем должно быть мое понимание отношений, но я до сих пор не могу понять, как вернуть все необходимые ресурсы, когда рецепты состоят из других компонентов, для которых требуются и другие Материалы.

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
)

Спасибо!

  • 0
    Выглядит как простой запрос без объединения. Просто против рецепт с заказом. Отредактируйте свой вопрос и покажите соответствующие схемы таблиц и их взаимосвязь, если вы действительно считаете, что необходимо объединение. Также добавьте запрос, который вы пробовали
  • 0
    Вы, вероятно, правы, у меня есть другие таблицы, но нет необходимости присоединяться к ним. Я могу легко получить ВЫБЕРИТЕ, ГДЕ Рецепт = тот, который я ищу, но тогда как мне заставить компоненты возвращать их Сырье? А потом сложить количества вместе?
Показать ещё 5 комментариев
Теги:
database

1 ответ

0
Лучший ответ

UPDATE/EDIT:

Обновлен для правильного расчета количества

Я изменил расположение таблицы, чтобы лучше сопоставлять данные, которые вы пытаетесь представить. Поскольку "рецепт" также может быть "материалом", я удалил таблицу рецептов и сохранил эти данные в таблице материалов.

Я также создал 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'

Результаты:

| 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'

Результаты:

| 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] |
  • 0
    Это только возвращает прямые ингредиенты для Липкого поршня, оно не разбивает ингредиенты, также необходимые для изготовления поршня, который является компонентом в липком поршне.
  • 0
    Согласно комментарию @Kodos, ваши данные должны быть нормализованы. Вы не хотите связывать таблицы, используя текстовые значения. Если не 3 таблицы, которые он предложил, то, по крайней мере, уникальный ключ автоинкремента и целочисленный ключ для «подкомпонентов». Связывание строк на основе текстового ключа использует больше ресурсов для каждого запроса и подвержено ошибкам. Например, «Поршень» не равен «поршню». Было бы полезно, если бы ваш вопрос включал схему таблицы. Схема может быть такой же простой, как показ оператора создания таблицы.
Показать ещё 8 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню