2014-10-17 68 views
0

我正在使用以下SQL來生成分層數據並努力解決如何讓孩子按排序順序ID值進行排序。任何意見如何將不勝感激。請注意,這不是我的SQL,它來自我修改的OpenCart的類別列表頁面。我嘗試將排序順序添加到一些地方,但似乎沒有任何區別。我想輸出是表明是根據列值對分層SQL行進行排序

| 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排序順序會對Sub1Sub2Sub3並沒有影響無那些會對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

注:這是我加入到澄清問題更多虛擬數據。小提琴將顯示顯著較少的數據

| 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 | 
+0

我有一個downvote沒有問題,但我希望人們至少會評論什麼需要改進之前 – 2014-10-17 15:00:05

回答

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

+0

謝謝,但我不認爲這會奏效。基本上,層次結構中的每個層次都需要根據'sort_order'和'parent_id'進行排序。我已經更新了該問題以提供更好的示例。此外,這裏的限制是不相關 – 2014-10-17 02:30:18

+0

嗯,我不知道我遵循訂購邏輯,唯一的區別是你想要的和你的當前是65和64切換,但爲什麼? – 2014-10-17 02:56:49

+0

我試圖找出它,它可能是一種情況,你需要使用一些條件聚合來獲得排序字段,但看到所有相關領域取消分組我看不到所需順序背後的推理,如果你可以有點擴展,我相信我們可以得到它。 – 2014-10-17 03:20:38

0

如果我正確理解你的問題,你可以通過排序順序由第一,然後才能砍名稱,訂單的最後一部分:

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 > | 
+---------+-----------+------------+----------------------------+-------------------+ 
+0

嗨Lennart。請看看我所做的更新以及Goat CO的回答。謝謝 – 2014-10-17 09:50:10

+0

好的,所以您需要的是深度優先搜索(DFS),其中兄弟姐妹按照排序順序進行排序。我不明白這是怎麼可能的(不改變模型)。爲了得到一個給定模型的DFS,你通常需要全名進行排序,這樣孩子們就可以直接在父代之後進行排序。但那麼排序順序不會有任何影響。作爲補充說明,請確保每個級別具有相同的長度。否則,分類將會中斷。抱歉無法提供幫助。 – Lennart 2014-10-18 08:54:08

+0

好的,謝謝Lennart,感謝你的時間,並試圖幫助 – 2014-10-18 11:41:35

相關問題