【问题标题】:Category and subcategory recursive query SQL类别和子类别递归查询SQL
【发布时间】:2021-02-19 02:02:52
【问题描述】:

我的递归查询有点问题。 我有一个酒吧菜单的数据库。 我们得到:类别,每个类别都有子类别,每个子类别都有多个项目。

数据库就是这个,里面有查询链接:

CREATE TABLE category (
  id int(10) unsigned NOT NULL AUTO_INCREMENT,
  title varchar(255) NOT NULL,
  parent_id int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (parent_id) REFERENCES category (id) 
    ON DELETE CASCADE ON UPDATE CASCADE
);


CREATE TABLE `items` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `cat_id` int unsigned DEFAULT NULL,
  `parent_id` int unsigned DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `cat_id` (`cat_id`),
  KEY `sub_id` (`parent_id`),
  CONSTRAINT `cat_id` FOREIGN KEY (`cat_id`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `sub_id` FOREIGN KEY (`parent_id`) REFERENCES `category` (`parent_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

BEGIN;
INSERT INTO `category` VALUES (1, 'Colazione', NULL);
INSERT INTO `category` VALUES (2, 'Pranzo', NULL);
INSERT INTO `category` VALUES (3, 'Primi piatti', 2);
INSERT INTO `category` VALUES (4, 'Second dish', 2);
INSERT INTO `category` VALUES (5, 'Other things for lunch', 2);
COMMIT;

-- ----------------------------
-- Records of items
-- ----------------------------
BEGIN;
INSERT INTO `items` VALUES (1, 1, NULL, 'Cornetto');
INSERT INTO `items` VALUES (2, 3, 2, 'Pasta al sugo 1');
INSERT INTO `items` VALUES (3, 3, 2, 'Pasta al sugo 2');
INSERT INTO `items` VALUES (4, 3, 2, 'Pasta al sugo 3');
INSERT INTO `items` VALUES (5, 3, 2, 'Pasta al sugo 1 X');
INSERT INTO `items` VALUES (6, 3, 2, 'Pasta al sugo 2 X');
INSERT INTO `items` VALUES (7, 4, 2, 'Pasta al sugo 3 X');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

查询:

with combine_trees as (
with make_tree as (
WITH RECURSIVE category_path  AS
(
  SELECT id, title, parent_id
    FROM category
    WHERE parent_id IS NULL
  UNION ALL
  SELECT c.id, c.title, c.parent_id
    FROM category_path AS cp JOIN category AS c
      ON cp.id = c.parent_id
)
SELECT cp.title, cp.id,
       if(cp.id = category.id,
          json_arrayagg(json_object('item_name', it.name)),
          json_object(cp.title, json_object('items',json_arrayagg(json_array(json_object('item_name', it.name))))))
        as tree
FROM category_path cp
INNER JOIN items it ON it.cat_id = cp.id
join category on category.id =  ifnull(cp.parent_id, cp.id)
group by cp.title, cp.id, category.id
)
select json_arrayagg(json_object(title, json_array('items', tree))) output_json from make_tree group by id
)
select json_object('menu',group_concat(output_json)) as output from combine_trees;

https://sqlize.online/

问题在于它没有将结果打印为 JSON,而是将其打印为单字符串格式。如果所有输出都是唯一的字符串,我们如何将其转换为 JSON?

【问题讨论】:

标签: mysql sql mysql-json


【解决方案1】:

在你的最后一行,

select json_object('menu',group_concat(output_json)) as output from combine_trees

您不能使用group_concat 组合从第二行到最后一行获得的 json 数组(例如 select json_arrayagg(...) output_json from make_tree group by id)。

你得到的每个数组看起来都像[...]group_concat 会给你[...], [...]。这不是一个有效的 json 数组(需要额外的括号括起来,例如[[...],[...]]),而是一个字符串,并从中创建一个 json 对象会给你,嗯,那个字符串作为值。

要组合您的 json 数组,您可以使用(和之前一样)json_arrayagg 而不是 group_concat,例如

select json_object('menu',json_arrayagg(output_json)) as output from combine_trees

【讨论】:

  • 问题是我在 json 中得到了 "items", [ 而不是 "items": [ 我现在得到的 json 是: "Colazione": [ "items", [ { " item_name": "Cornetto" } ] ] } ],并且 items 应该是 "items": [ 实际上它是错误的
  • 您的问题是为什么“将其打印为单字符串格式”。如果你的 json 有不同的问题,你需要问另一个问题。我会假设你的问题可能是json_array('items', tree))(它创建两个条目而不是一个值为树的键),所以也许试试json_object('items', tree))(如果“树”是一个数组,应该给你"items": [... )。但同样,对于不同的问题,请创建一个具有预期(和当前,不正确)输出的新问题(以及直接包含的代码,如草莓编辑后的当前问题)。
猜你喜欢
  • 2011-12-14
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多