mysql - 根据列值对分层 SQL 行进行排序

标签 mysql sql sorting

我正在使用以下 SQL 来生成分层数据,并努力弄清楚如何让子项按排序顺序 ID 值进行排序。任何有关如何的建议将不胜感激。请注意,这不是我的 SQL,它取 self 修改过的 OpenCart 的类别列表页面。我尝试在几个地方添加排序顺序,但似乎没有任何区别。我想要显示的输出是

| PAGE_ID |                       NAME | PARENT_ID | SORT_ORDER |
|---------|----------------------------|-----------|------------|
|      75 |                     Index4 |         0 |         -7 |
|      60 |                      Index |         0 |          0 |
|      68 |             Index  >  Sub6 |        60 |         -6 |
|      61 |             Index  >  Sub1 |        60 |          1 |
|      65 | Index  >  Sub1  >  SubSub2 |        61 |          4 |
|      64 | Index  >  Sub1  >  SubSub1 |        61 |          6 |
|      67 |             Index  >  Sub5 |        60 |          1 |
|      62 |             Index  >  Sub2 |        60 |          2 |
|      63 |             Index  >  Sub3 |        60 |          5 |
|      69 | Index  >  Sub3  >  SubSub3 |        63 |          1 |
|      71 | Index  >  Sub3  >  SubSub5 |        63 |          2 |
|      72 | Index  >  Sub3  >  SubSub4 |        63 |          5 |
|      70 | Index  >  Sub3  >  SubSub6 |        63 |          9 |
|      66 |             Index  >  Sub4 |        60 |          7 |
|      74 |                     Index3 |         0 |          1 |
|      73 |                     Index2 |         0 |          4 |

请注意,树的每个子子集都根据 sort_order 列单独排序,因此 Index 的排序顺序不会影响 Sub1 Sub2Sub3 并且这些都不会对 SubSub1SubSub2SubSub3

Here's the SQL Fiddle

DROP TABLE IF EXISTS `oc_page`;
CREATE TABLE `oc_page` (
  `page_id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL DEFAULT '0',
  `sort_order` int(3) NOT NULL DEFAULT '0',
  `status` tinyint(1) NOT NULL,
  `date_added` datetime NOT NULL,
  `date_modified` datetime NOT NULL,
  PRIMARY KEY (`page_id`),
  KEY `parent_id` (`parent_id`)
) ENGINE=MyISAM AUTO_INCREMENT=66 DEFAULT CHARSET=utf8;

BEGIN;
INSERT INTO `oc_page` VALUES ('60', '0', '0', '1', '2014-10-16 02:49:41', '2014-10-17 02:03:15'), ('61', '60', '1', '1', '2014-10-17 02:03:02', '2014-10-17 03:17:20'), ('62', '60', '2', '1', '2014-10-17 02:18:59', '2014-10-17 03:16:20'), ('63', '60', '3', '1', '2014-10-17 02:23:27', '2014-10-17 03:16:49'), ('64', '61', '6', '1', '2014-10-17 03:17:49', '2014-10-17 03:17:58'), ('65', '61', '4', '1', '2014-10-17 03:18:36', '2014-10-17 03:18:36');
COMMIT;

DROP TABLE IF EXISTS `oc_page_description`;
CREATE TABLE `oc_page_description` (
  `page_id` int(11) NOT NULL,
  `language_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `meta_title` varchar(255) NOT NULL,
  `meta_description` varchar(255) NOT NULL,
  `meta_keyword` varchar(255) NOT NULL,
  PRIMARY KEY (`page_id`,`language_id`),
  KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

BEGIN;
INSERT INTO `oc_page_description` VALUES ('60', '1', 'Index', '<p>Test</p>', 'Test', '', ''), ('61', '1', 'Sub1', 'Sub1', 'Sub1', '', ''), ('64', '1', 'SubSub1', 'SubSub1', 'SubSub1', '', ''), ('65', '1', 'SubSub2', 'SubSub2', 'SubSub2', '', ''), ('62', '1', 'Sub2', 'Sub2', 'Sub2', '', ''), ('63', '1', 'Sub3', 'Sub3', 'Sub3', '', '');
COMMIT;

DROP TABLE IF EXISTS `oc_page_path`;
CREATE TABLE `oc_page_path` (
  `page_id` int(11) NOT NULL,
  `path_id` int(11) NOT NULL,
  `level` int(11) NOT NULL,
  PRIMARY KEY (`page_id`,`path_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

BEGIN;
INSERT INTO `oc_page_path` VALUES ('60', '60', '0'), ('61', '61', '1'), ('61', '60', '0'), ('62', '62', '1'), ('62', '60', '0'), ('63', '63', '1'), ('63', '60', '0'), ('64', '64', '2'), ('64', '60', '0'), ('64', '61', '1'), ('65', '60', '0'), ('65', '61', '1'), ('65', '65', '2');
COMMIT;

DROP TABLE IF EXISTS `oc_page_to_store`;
CREATE TABLE `oc_page_to_store` (
  `page_id` int(11) NOT NULL,
  `store_id` int(11) NOT NULL,
  PRIMARY KEY (`page_id`,`store_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

BEGIN;
INSERT INTO `oc_page_to_store` VALUES ('60', '0'), ('61', '0'), ('62', '0'), ('63', '0'), ('64', '0'), ('65', '0');
COMMIT;

查询 1:

SELECT pp.page_id AS page_id,
       GROUP_CONCAT(pd1.name
                    ORDER BY pp.level SEPARATOR '  >  ') AS name,
       p1.parent_id,
       p1.sort_order
FROM oc_page_path pp
LEFT JOIN oc_page p1 ON (pp.page_id = p1.page_id)
LEFT JOIN oc_page p2 ON (pp.path_id = p2.page_id)
LEFT JOIN oc_page_description pd1 ON (pp.path_id = pd1.page_id)
LEFT JOIN oc_page_description pd2 ON (pp.page_id = pd2.page_id)
WHERE pd1.language_id = '1'
  AND pd2.language_id = '1'
GROUP BY pp.page_id
ORDER BY name ASC LIMIT 0,20

<强> Results :

注意:这是我添加的虚拟数据,以进一步澄清问题。 fiddle 将显示明显更少的数据

| PAGE_ID |                       NAME | PARENT_ID | SORT_ORDER |
|---------|----------------------------|-----------|------------|
|      60 |                      Index |         0 |          0 |
|      61 |             Index  >  Sub1 |        60 |          1 |
|      64 | Index  >  Sub1  >  SubSub1 |        61 |          6 |
|      65 | Index  >  Sub1  >  SubSub2 |        61 |          4 |
|      62 |             Index  >  Sub2 |        60 |          2 |
|      63 |             Index  >  Sub3 |        60 |          5 |
|      69 | Index  >  Sub3  >  SubSub3 |        63 |          1 |
|      70 | Index  >  Sub3  >  SubSub6 |        63 |          9 |
|      71 | Index  >  Sub3  >  SubSub5 |        63 |          2 |
|      72 | Index  >  Sub3  >  SubSub4 |        63 |          5 |
|      66 |             Index  >  Sub4 |        60 |          7 |
|      67 |             Index  >  Sub5 |        60 |          1 |
|      68 |             Index  >  Sub6 |        60 |         -6 |
|      73 |                     Index2 |         0 |          4 |
|      74 |                     Index3 |         0 |          1 |
|      75 |                     Index4 |         0 |         -7 |

最佳答案

您可以简单地使用子查询将显示ORDER与内部ORDER分开:

SELECT *
FROM (
      SELECT pp.page_id AS page_id,
             GROUP_CONCAT(pd1.name
                          ORDER BY pp.level SEPARATOR '  >  ') AS name,
             p1.parent_id,
             p1.sort_order
      FROM oc_page_path pp
      LEFT JOIN oc_page p1 ON (pp.page_id = p1.page_id)
      LEFT JOIN oc_page p2 ON (pp.path_id = p2.page_id)
      LEFT JOIN oc_page_description pd1 ON (pp.path_id = pd1.page_id)
      LEFT JOIN oc_page_description pd2 ON (pp.page_id = pd2.page_id)
      WHERE pd1.language_id = '1'
        AND pd2.language_id = '1'
      GROUP BY pp.page_id
      ORDER BY name ASC LIMIT 0,20
        ) sub
ORDER BY Sort_Order

演示:SQL Fiddle

注意:由于LIMIT,我假设您需要内部ORDER BY,因为如果没有,您可以只ORDER BY Sort_Order

关于mysql - 根据列值对分层 SQL 行进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26416734/

相关文章:

c++ - 基于排序的分区(如快速排序)

php - 在 mysql、php 中搜索年龄范围

php - 将时间值与数据库进行比较以停止重复条目

sql - 分割字符串并获取最后一个元素

mysql - 在 mysql 中使用函数创建列别名?

c - 仅使用 while 和 if 对数组进行排序

c++ - 对二维字符数组进行排序 C++

mysql - 带有 COUNT 的子查询 (mysql)

php - 当搜索参数值为 null 或为空时选择所有行 [mysql]

php - 在 mySQL 或 PHP 数组中对结果进行排序?