如何在SQL中按顺序排序?

时间:2011-11-17 18:21:02

标签: sql sql-order-by

我正在尝试创建一个SQL语句,它将在SilkCentral Test Manager中重新创建分层容器/文件夹/测试结构。

Silk Ordering - Screen Shot

  • 测试容器没有ParentID
  • 测试文件夹包含ParentID和IsLeaf = 0
  • 测试包含ParentID和IsLeaf = 1

此查询将生成所有测试容器,文件夹和测试:

SELECT "NodeID", "ParentID", "Name", "IsLeaf", "OrderNumber"
FROM "Silk"."TM_TestPlanNodes" AS TPN
WHERE PROJECTID = 36
ORDER BY "ParentID", "OrderNumber", "IsLeaf"

以下是一些结果:

NodeID  ParentID    Name                        IsLeaf  OrderNumber 
65408               Installation and Upgrades   0       0   
65445               Connectivity                0       1   
65448               Focus                       0       2   
65409               GINA / PLAP                 0       3   
65446               Graphical User Interface    0       4   
71038               Login Properties            0       5   
65449               Miscellaneous               0       6   
70636               Net Firewall                0       7   
70998               Software Updates            0       8   
65447               Third-party Services        0       9   
70805               SilkTest Automated Tests    0       10  
68812   65408       0. Setup                    0       0
65454   65408       1. Installations & Upgrades 0       1   
65450   65408       Typical/Custom Installation 0       2   

我希望这个订购代替: Silk Ordering

ParentID已排序,但如果存在具有ParentID = thePreviousNode'sID的节点,则接下来选择该节点。如果有多个节点,则应由IsLeaf和OrderNumber订购。

如何做到这一点?我的能力非常有限,因为我认为非常复杂的语法最终会在Silk中引发错误。我打算尝试嵌套的SELECT语句:

SELECT "NodeID", "ParentID", "Name","IsLeaf" 
FROM "Silk"."TM_TestPlanNodes" 
WHERE PROJECTID = '36'AND ParentID LIKE (
  SELECT ParentID 
  FROM "Silk"."TM_TestPlanNodes" 
  WHERE NAME = 'Installation and Upgrades')

但是这会出现这样的错误:“无法执行报告查询:子查询返回的值超过1。当子查询跟随=,!=,<,< =,>,> =时,不允许这样做或者当子查询用作表达式时。“

这就是为什么我在摆弄Order By。

2 个答案:

答案 0 :(得分:2)

您可以使用递归cte创建隐藏列并按该列排序。隐藏列应该是类似的东西:

WITH cte (NodeID, ParentID, Name, IsLeaf, [Order])
AS
(
    SELECT NodeID, ParentID, Name, IsLeaf, cast(NodeID as nvarchar(10))
    FROM "Silk"."TM_TestPlanNodes" 
    WHERE PROJECTID = '36'
    UNION ALL
    SELECT "NodeID", "ParentID", "Name","IsLeaf", cast(leftNode.ParentID as nvarchar(10)) + cast(leftNode.NodeID as nvarchar(10))
    FROM "Silk"."TM_TestPlanNodes" as leftNode
    INNER JOIN cte on cte.NodeID = leftNode.ParentID
    WHERE leftNode.ParentID = cte.NodeID
)
select  "NodeID", "ParentID", "Name","IsLeaf"  from cte
order by cast([Order] as nvarchar(50))

这是用记事本写的,所以可能有一些错误,但想法是制作一个[order]列,例如 65530 654086554569530 (parent_parent,父节点和节点)

修改

只有当id长度为5个字符时才有效,但是从这里你可以进行适当的调整。

答案 1 :(得分:1)

尽管它可能不是一个完美的契合,但它与自联合列表中的父子记录的嵌套分层表示非常接近,并且包含了正确的排序问题。您可能需要为您的表稍微调整一下,但here's a link to a prior solution

澄清菜单和相应数据的问题。

id    |     parentid     |       name
1     |        0         |      CatOne
2     |        0         |      CatTwo
3     |        0         |      CatThree
4     |        1         |      SubCatOne
5     |        1         |      SubCatOne2
6     |        3         |      SubCatThree

期望的输出

CatOne 1
--SubCatOne 4
--SubCatOne2 5
CatTwo 2
CatThree 3
--SubCatThree 6

第一种情况是基于父母对所有类似ID进行预分组......因此,当父ID为0时,它是最顶层的,所以我们保留它的ID。然后,在它下面的任何孩子,我们想要他们各自的PARENT ID,所以所有相同的都被正确预先分组。

SECOND group by的目的是强制将表示实际TOP LEVEL菜单项的条目放在列表顶部,而不管子条目如何。

假设您有一个已经建立了ID的表,现在您将新项目添加到位置ID = 7,用于“新顶级”,并希望将ID#2和3移动到新的“顶部” -level section 。如果您只是使用第一个CASE查询,您的记录将被模拟返回为

ID   Parent   Name  (natural order from the table)
2    7        CatTwo
3    7        CatThree
7    0        New Category.  (we want THIS one in FIRST POSITION of the group)

正如您所看到的,这将是子分组顺序的错误表示。顶级项目实际上位于第3位...为了将它带到前面,我们现在进行子分组并说...如果记录的父ID = 0,则将其排序为好像它是'1'优先级。其他任何东西都被认为是'2'优先级,并会像

那样模拟结果
ID   Parent   Name             SubPrioritySort
7    0        New Category.    1
2    7        CatTwo           2
3    7        CatThree         2

由于您实际上并未在结果查询中返回这些“CASE”值,否则您无法直观地看到它...但是对于grins,请将它们作为列添加到查询中以查看其影响。希望这能为你澄清答案。

在您的问题中,您显然可以将排序顺序列添加到此查询的基础中。