2

在创建 SQL 查询以显示一个表中的类别和子类别时,我遇到了很多麻烦。我有以下列:

category_id
category_name
category_parent
category_order

基本上我想要产生的结果是这样的

parent category 1
sub category 1
sub category 2
parent category 2
sub category 1
sub category 2
sub category 3
parent category 3
sub category 1

如果 category_order 设置为 0,则类别或子类别应根据它们创建的顺序进行排序。为此,我计划按 id 排序。

如果可能的话,我想使用 UNION 以便它们已经有序,我只需要循环。谁能帮我建立一个查询。

实际上我已经有一个使用 JOIN 但结果并不像我想要的那样精确。

这是我之前的查询:

SELECT
fcat.id fcat_id,
fcat.name fcat_name,
fcat.order fcat_order,
fcat.parent fcat_parent,
fsub.id fsub_id,
fsub.name fsub_name,
fsub.order fsub_order,
fsub.parent fsub_parent
FROM forum_categories AS fcat
LEFT OUTER JOIN forum_categories AS fsub ON fcat.id = fsub.parent
ORDER BY ISNULL(fcat.order) ASC, fcat.id ASC, ISNULL(fsub.order) ASC, fsub.id ASC

但是,它不会对子类别进行排序,因为父类别和子类别是连接在一起的。我的查询只对父母进行排序。

4

6 回答 6

5

我认为订购是这里有趣的部分。特别是,类别内的排序很有趣。我做了一个小提琴来说明这一点:http ://sqlfiddle.com/#!8/78059/3

这是查询:

select * from (
  select c.*,
  coalesce(nullif(c.parent, 0), c.id) as groupID,
  case when c.parent = 0 then 1 else 0 end as isparent,
  case when p.`order` = 0 then c.id end as orderbyint
  from category c
  left join category p on p.id = c.parent
) c order by groupID, isparent desc, orderbyint, name

我们可以用它是否是父类来注释每个类别。然后我们可以对类别进行分组。在每个组中,订单取决于父订单。这里我是根据 id whenparent.order为 0 进行排序,如果不为 0orderbyint则为 null,然后我们就按name.

于 2013-06-29T18:59:49.857 回答
2

当树的深度限制为 2 时:

select c1.*, 
       c2.*,
       if (c2.category_parent is NULL, "parent category", "sub category") as text
from cat c1 left join cat c2 
    on c1.category_id = c2.category_parent
order by c1.category_id, c2.category_id

您可以使用条件c2.category_parent is NULL来测试类别的级别。

于 2013-06-29T17:56:16.600 回答
0

我遇到了同样的问题并测试了许多示例或 Tomas 和 JTseng 解决方案。这些缺少数字排序或子类别排序。我修改了 JTseng 查询,现在(对我来说)没问题,这样:

SELECT c.*,
  CASE WHEN isnull(is_par.cat_id) THEN c.cat_sort_order ELSE is_par.cat_sort_order END as sort_order,
  CASE WHEN isnull(is_par.cat_id) THEN c.cat_id ELSE is_par.cat_id END as catid ,
  CASE WHEN isnull(is_par.cat_id) THEN 0 ELSE c.cat_sort_order END as subcat_order
FROM `category` c
LEFT JOIN `category` is_par ON is_par.cat_id = c.cat_parent_id
ORDER BY  sort_order , catid, subcat_order

我在测试解决方案后编写了这个解决方案,其中通过创建一个由三个字符串组成的连接字符串来进行排序:第一个字符串用于父类别的主要排序顺序,第二个字符串用于对父类别及其子类别进行分组,第三个字符串用于排序父母和他们的孩子根据孩子排序(为了把父母猫放在第一位,他们被赋予了一个虚拟的子猫排序顺序设置为0)。但是这个字符串排序给出了字母排序,而不是数字排序。因此,像 JTseng 这样将排序字符串转换为额外的数字字段:

  • 第一个 CASE WHEN 用于检测类别是否为父类别。如果是父类,则保留父类的排序顺序,如果是子类,则其排序顺序被父类的排序顺序替换
  • 第二个 CASE WHEN 用于替换方式,一个子类别 id 为其父类别 id(这相当于 JTseng groupid)
  • 第三个 CASE WHEN 用于设置 0 为父子排序顺序并保持子猫排序顺序

要查看 LEFT JOIN 操作,只需在您的 phpMyAdmin 页面中执行此查询:

SELECT c.cat_id as ccatid,c.cat_sort_order as ccatsortorder, is_par.cat_id as isparcatid,is_par.cat_parent_id as ispar_catparentid,is_par.cat_sort_order as isparcatsortorder,
  CASE WHEN isnull(is_par.cat_id) THEN c.cat_sort_order ELSE is_par.cat_sort_order END as sort_order,
  CASE WHEN isnull(is_par.cat_id) THEN c.cat_id ELSE is_par.cat_id END as catid,
  CASE WHEN isnull(is_par.cat_id) THEN 0 ELSE c.cat_sort_order END as subcat_order
FROM `category` c
LEFT JOIN `category` is_par ON is_par.cat_id = c.cat_parent_id
于 2013-10-13T08:37:40.120 回答
0

我找到了一个简单的方法来做到这一点。它按层次结构和字母顺序排列。

首先我把看例子需要的SQL放到:

CREATE TABLE IF NOT EXISTS `categories` (
  `category_id` int(11) NOT NULL AUTO_INCREMENT,
  `category_parent` int(11) NOT NULL,
  `category_name` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  PRIMARY KEY (`category_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci;

现在快速插入有结果:

INSERT INTO categories( category_id, category_parent, category_name) 值 (1, 0, 'Category number 1'), (2, 0, 'Category number 2'), (3, 0, 'Category number 3'), (4, 0, 'Category number 4'), (5, 0, 'Category number 5'), (6, 0, 'Category number 6'), (7, 2, 'First Subcategory of category 2'), (8, 2, 'Second类别 2 的子类别'), (9, 2, '类别 2 的第三个子类别(必须先出现,因为字母顺序)'), (10, 1, '类别编号 1 的第一个子类别'), (11, 1 , 'Ans second Subcategory of category number 1 (必须首先出现,因为字母顺序)');

和 SQL 语句:

SELECT category_id,category_parent,category_name,
(CASE
    WHEN category_parent=category_id OR category_parent=0  THEN category_id
    WHEN category_parent<>category_id THEN category_parent
END) AS 'the_parent'
FROM categories ORDER BY the_parent ASC, category_parent ASC, category_name ASC

我希望它有用

于 2015-01-19T17:11:16.680 回答
0

这是我对 3 个子类别 level1、level2 和 level3 深度的回答

SELECT
    main.id AS main_id,
    level1.id AS level1_id,
    level2.id AS level2_id,
    level3.id AS level3_id
FROM
    categories AS main
LEFT OUTER JOIN categories AS level1 ON level1.parent_id = main.id
LEFT OUTER JOIN categories AS level2 ON level2.parent_id = level1.id
LEFT OUTER JOIN categories AS level3 ON level3.parent_id = level2.id
WHERE
    main.parent_id = "ID-OF-MAIN-CATEGORY"
ORDER BY
    main_id,
    level1_id,
    level2_id,
    level3_id

您的查询看起来与此类似(从示意图上讲)

在此处输入图像描述

希望有帮助

于 2015-05-08T13:47:22.063 回答
0
select *, if (parent_category_id is NULL, id, concat(parent_category_id, id)) as o
from category
order by o

样本数据

于 2019-06-09T20:12:00.993 回答