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

时间:2014-10-17 01:55:26

标签: mysql sql sorting

我使用以下SQL生成分层数据,并努力弄清楚如何让孩子按排序顺序ID值进行排序。任何关于如何欣赏的建议。请注意,这不是我的SQL,它取自我已修改的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,{{1} }或Sub2这些都不会对Sub3SubSub1SubSub2

产生影响

Here's the SQL Fiddle

SubSub3

查询1

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;

Results

注意:这是我添加的虚拟数据,以便更多地澄清问题。小提琴将显示更少的数据

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

2 个答案:

答案 0 :(得分:1)

您可以简单地使用子查询与内部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

注意:由于ORDER BY,我认为您需要内部LIMIT,因为如果不是,您只能ORDER BY Sort_Order

答案 1 :(得分:0)

如果我理解你的问题你可以砍掉名字的最后一部分,先按顺序排序然后按sort_order排序:

select page_id, parent_id, sort_order, name
     , substr(name, 1, length(name) - locate(' > ', reverse(name))) as path 
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, p1.parent_id, p1.sort_order
) as t 
order by path, sort_order;

+---------+-----------+------------+----------------------------+-------------------+
| page_id | parent_id | sort_order | name                       | path              |
+---------+-----------+------------+----------------------------+-------------------+
|      60 |         0 |          0 | Index                      | Index             |
|      61 |        60 |          1 | Index  >  Sub1             | Index  >          |
|      62 |        60 |          2 | Index  >  Sub2             | Index  >          |
|      63 |        60 |          3 | Index  >  Sub3             | Index  >          |
|      65 |        61 |          4 | Index  >  Sub1  >  SubSub2 | Index  >  Sub1  > |
|      64 |        61 |          6 | Index  >  Sub1  >  SubSub1 | Index  >  Sub1  > |
+---------+-----------+------------+----------------------------+-------------------+