2016-03-03 34 views
2

非常令人困惑的标题!让我详细说明一下。删除递归CTE中包含ID的所有较短的子序列

我有两个表;一个表示模块(可包含其他模块的某种类型的网页),称为module_info,另一个表示模块层次结构中每个页面的位置,称为www_menu

module_info

+----------+------------+---------+ 
| moduleID | modulename | menu_id | 
+----------+------------+---------+ 
|  1 | tests  |  1 | 
|  2 | docs  |  2 | 
|  3 | mail  |  3 | 
|  4 | networks |  4 | 
|  5 | payroll |  5 | 
|  6 | admin  |  6 | 
|  7 | travel  |  7 | 
|  8 | bios  |  8 | 
+----------+------------+---------+ 

www_menu

+--------+--------+-------------------+------------------+ 
| menuID | parent |  title  |  location  | 
+--------+--------+-------------------+------------------+ 
|  1 |  0 | Tests    | modules/tests | 
|  2 |  0 | Testing Documents | modules/docs  | 
|  3 |  0 | Mailing Lists  | modules/mail  | 
|  4 |  1 | Network Services | modules/networks | 
|  5 |  1 | Payroll   | modules/payroll | 
|  6 |  2 | Administration | modules/admin | 
|  7 |  3 | Travel   | modules/travel | 
|  8 |  4 | Biographies  | modules/bios  | 
+--------+--------+-------------------+------------------+ 

这里是我的查询中显示的层次:

WITH [root] AS 
(
    SELECT  www.menuID 
       ,CAST(www.title + ' (' + mi.modulename + ')' AS VARCHAR(200)) AS [path] 
       ,CAST(mi.id AS VARCHAR(20)) AS ids 
    FROM  [dbo].[module_info] AS mi 
    INNER JOIN [dbo].[WWW_Menu] www ON www.menuid = mi.menu_id 
    WHERE  www.location LIKE 'modules/%' 
UNION ALL 
    SELECT  leaf.menuID 
       ,CAST([root].[path] + ' > ' + leaf.title AS VARCHAR(200)) 
       ,CAST([root].ids + ',' + CONVERT(VARCHAR(4), mi.id) AS VARCHAR(20)) 
    FROM  [dbo].[WWW_Menu] AS leaf 
    INNER JOIN [root] ON leaf.parent = [root].menuID 
    INNER JOIN [dbo].[module_info] AS mi ON leaf.menuID = mi.menu_id 
) 
SELECT [path], ids FROM [root] 

并从上面的两个表运行的结果:

+----------------------------------------+-------+ 
|     path     | ids | 
+----------------------------------------+-------+ 
| Tests         | 1  | 
| Testing Documents      | 2  | 
| Mailing Lists       | 3  | 
| Network Services      | 4  | 
| Payroll        | 5  | 
| Administration       | 6  | 
| Travel         | 7  | 
| Biographies       | 8  | 
| Tests > Network Services    | 1,4 | 
| Tests > Payroll      | 1,5 | 
| Testing Documents > Administration  | 2,6 | 
| Mailing Lists > Travel     | 3,7 | 
| Network Services > Biographies   | 4,8 | 
| Tests > Network Services > Biographies | 1,4,8 | 
+----------------------------------------+-------+ 

我将在选择框中显示这些结果,以便在所选模块内搜索文档。这是事情; Biographies,Network Services > BiographiesTests > Network Services > Biographies是相同的模块。

对于每个模块,我只是想显示该模块

+----------------------------------------+-------+ 
|     path     | ids | 
+----------------------------------------+-------+ 
| Tests         | 1  | 
| Testing Documents      | 2  | 
| Mailing Lists       | 3  | 
| Tests > Network Services    | 1,4 | 
| Tests > Payroll      | 1,5 | 
| Testing Documents > Administration  | 2,6 | 
| Mailing Lists > Travel     | 3,7 | 
| Tests > Network Services > Biographies | 1,4,8 | 
+----------------------------------------+-------+ 

在结束最长的层次串也许这是不正常一个SQL问题,并更好地通过某种迭代完成服务器端。但是,针对此问题的自包含SQL解决方案将是我的首选选项。谢谢。

回答

3

一种方法会涉及很多字符串操作。相反,当您浏览列表时,请跟踪添加到列表中的最后一个模块。然后使用row_number()获得每个“最后”模块的最长时间:

WITH [root] AS (
    SELECT www.menuID, 
      CAST(www.title + ' (' + mi.modulename + ')' AS VARCHAR(200)) AS [path], 
      CAST(mi.id AS VARCHAR(20)) AS ids, 
      mi.id as lastId 
    FROM [dbo].[module_info] mi INNER JOIN 
     [dbo].[WWW_Menu] www 
     ON www.menuid = mi.menu_id 
    WHERE www.location LIKE 'modules/%' 
    UNION ALL 
    SELECT leaf.menuID, 
      CAST([root].[path] + ' > ' + leaf.title AS VARCHAR(200)), 
      CAST([root].ids + ',' + CONVERT(VARCHAR(4), mi.id) AS VARCHAR(20)), 
      mi.id 
    FROM [dbo].[WWW_Menu] leaf INNER JOIN 
     [root] 
     ON leaf.parent = [root].menuID INNER JOIN 
     [dbo].[module_info] mi 
     ON leaf.menuID = mi.menu_id 
    ) 
SELECT [path], ids 
FROM (SELECT r.*, 
      ROW_NUMBER() OVER (PARTITION BY lastId ORDER BY length(path) DESC) as seqnum 
     FROM [root] r 
    ) r 
WHERE seqnum = 1; 
+0

这很好,谢谢。 – wdonahoe