Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL select查询中的排序结果_Sql_Sql Server_Tsql_Select - Fatal编程技术网

SQL select查询中的排序结果

SQL select查询中的排序结果,sql,sql-server,tsql,select,Sql,Sql Server,Tsql,Select,假设我有一个名为Events的表,其数据如下所示: ID | Name | ParentEvent ----+----------------+----------------- 0 | Happy Event | NULL 1 | Sad Event | NULL 2 |Very Happy Event| 0 3 | Very Sad Event | 1 4 | H

假设我有一个名为Events的表,其数据如下所示:

  ID |      Name      |    ParentEvent
 ----+----------------+-----------------
   0 |   Happy Event  |       NULL
   1 |    Sad Event   |       NULL
   2 |Very Happy Event|        0
   3 | Very Sad Event |        1
   4 | Happiest Event |        2
   5 |Unpleasant Event|        1
我如何查询此表以获得返回的结果

具有非null ParentEvent的事件直接出现在ID与ParentEvent匹配的事件之后 ParentEvent为null的事件的深度为0。如果某个事件的深度为n,则作为父事件的任何事件的深度均为n+1。 只要结果满足前两个条件,结果出现的顺序就无关紧要。 对于上面给出的表,我想得到一个如下的结果集

  ID |      Name      |  ParentEvent |  Depth |
 ----+----------------+--------------+--------+
   0 |   Happy Event  |      NULL    |    0   |  
   2 |Very Happy Event|       0      |    1   |
   4 | Happiest Event |       2      |    2   |
   1 |    Sad Event   |      NULL    |    0   |
   3 | Very Sad Event |       1      |    1   |
   5 |Unpleasant Event|       1      |    1   |
如何构造SQL查询以获取此结果集?我使用的是T-SQL,但如果您可以在任何类型的SQL中执行此操作,请继续回答。

测试数据

查询Sql Server 2005+

;WITH ClassHierarchy_CTE (CID, ClassID_Join, Level)
AS
(
SELECT ID, ID AS Join_Class, 0
FROM   hierarchy AS c

UNION ALL
SELECT cte.CID, h.ParentID, Level + 1
FROM   hierarchy AS h INNER JOIN ClassHierarchy_CTE as cte
ON     h.ID = cte.ClassID_Join
)
SELECT    CTE.CID      AS ID
        , Hic.NAME     AS NAME
        , Hic.ParentID AS ParentEvent 
        , COUNT(*)-1   AS Depth    
FROM    ClassHierarchy_CTE CTE INNER JOIN hierarchy Hic
ON      CTE.CID = Hic.ID
WHERE   ClassID_Join IS NOT NULL
GROUP BY CTE.CID, Hic.NAME, Hic.ParentID
结果集


以下查询都返回您要求的确切结果集。所有这些工作都是通过计算到根节点的完整路径,并使用某种技术使该路径能够按顺序排列

SQLServer2008及以上版本。在这里,通过转换为hierarchyid数据类型,SQLServer可以正确地处理排序

WITH Data AS (
   SELECT
      ID,
      Name,
      ParentID,
      Depth = 0,
      Ancestry = '/' + Convert(varchar(max), ID) + '/'
   FROM
      hierarchy
   WHERE
      ParentID IS NULL
   UNION ALL
   SELECT
      H.ID,
      H.Name,
      H.ParentID,
      D.Depth + 1,
      Ancestry = D.Ancestry + Convert(varchar(max), H.ID) + '/'
   FROM
      Data D
      INNER JOIN hierarchy H
         ON H.ParentID = D.ID
)
SELECT
   ID,
   Name,
   ParentID,
   Depth
FROM Data
ORDER BY Convert(hierarchyid, Ancestry);
SQLServer2005及以上版本。我们可以将ID值转换为字符串,并将它们填充出来,以便进行排序

WITH Data AS (
   SELECT
      ID,
      Name,
      ParentID,
      Depth = 0,
      Ancestry = Right('0000000000' + Convert(varchar(max), ID), 10)
   FROM
      hierarchy
   WHERE
      ParentID IS NULL
   UNION ALL
   SELECT
      H.ID,
      H.Name,
      H.ParentID,
      Depth + 1,
      Ancestry = D.Ancestry + Right('0000000000' + Convert(varchar(max), H.ID), 10)
   FROM
      Data D
      INNER JOIN hierarchy H
         ON H.ParentID = D.ID
)
SELECT
   ID,
   Name,
   ParentID,
   Depth
FROM Data
ORDER BY Ancestry;
此外,我们还可以使用varbinary,否则,这与前面的查询相同:

WITH Data AS (
   SELECT
      ID,
      Name,
      ParentID,
      Depth = 0,
      Ancestry = Convert(varbinary(max), Convert(varbinary(4), ID))
   FROM
      hierarchy
   WHERE
      ParentID IS NULL
   UNION ALL
   SELECT
      H.ID,
      H.Name,
      H.ParentID,
      Depth + 1,
      Ancestry = D.Ancestry + Convert(varbinary(4), H.ID)
   FROM
      Data D
      INNER JOIN hierarchy H
         ON H.ParentID = D.ID
)
SELECT
   ID,
   Name,
   ParentID,
   Depth
FROM Data
ORDER BY Ancestry;
SQL Server 2000及更高版本,允许树的最大深度为800级:

SELECT
   *,
   Ancestry = CASE WHEN ParentID IS NULL THEN Convert(varchar(8000), Right('0000000000' + Convert(varchar(10), ID), 10)) ELSE '' END,
   Depth = 0
INTO #hierarchy
FROM hierarchy;

WHILE @@RowCount > 0 BEGIN
   UPDATE H
   SET
      H.Ancestry = P.Ancestry + Right('0000000000' + Convert(varchar(8000), H.ID), 10),
      H.Depth = P.Depth + 1
   FROM
      #hierarchy H
      INNER JOIN #hierarchy P
         ON H.ParentID = P.ID
   WHERE
      H.Ancestry = ''
      AND P.Ancestry <> '';
END;

SELECT
   ID,
   Name,
   ParentID,
   Depth
FROM #hierarchy
ORDER BY Ancestry;

DROP TABLE #hierarchy;

同样的varbinary转换也可以完成,允许多达2000层的深度。

这只是补充了M.Ali的答案。我意识到OP说,只要结果满足前两个条件,结果出现的顺序并不重要。但是,通过向查询中添加跟踪层次结构路径的列,可以显示与问题中相同的结果

;WITH CTE
AS
(
  SELECT 
    ID, 
    NAME,
    ParentID,
    0 as Depth,
    convert(varbinary(max), convert(varbinary(2), ID)) as ThePath
  FROM   hierarchy
  WHERE ParentID is null

  UNION ALL

  SELECT 
    h.ID, 
    h.NAME,
    h.ParentID, 
    cte.Depth + 1,
    cte.ThePath + convert(varbinary(max), convert(varbinary(2), h.ID)) as ThePath
  FROM   hierarchy AS h 
  INNER JOIN CTE as cte
  ON h.ParentID = cte.ID
)
SELECT 
  ID, 
  NAME, 
  ParentID, 
  Depth, 
  ThePath
FROM CTE 
ORDER BY ThePath
这会像这样显示结果

ID          NAME                           ParentID    Depth       ThePath
----------- ------------------------------ ----------- ----------- ---------------
0           Happy Event                    NULL        0           0x0000
2           Very Happy Event               0           1           0x00000002
4           Happiest Event                 2           2           0x000000020004
1           Sad Event                      NULL        0           0x0001
3           Very Sad Event                 1           1           0x00010003
5           Unpleasant Event               1           1           0x00010005

Oracle使用CONNECT BY子句哪个SQL Server/ASE版本?是-但OP也要求提供任何解决方案。。也许在调查中会有所帮助我没有搜索,但你可以在T中找到一些文章或参考资料,通过解决方案进行连接SQL@M.Ali:您似乎误解了问题-您需要阅读问题中所述的条件,以理解为什么结果按原来的顺序排列。在任何情况下,请不要在其他人的问题中编辑代码和输出,因为这样做会完全改变问题的含义。这如何回答要求事件,即具有非空ParentEvent的事件直接出现在ID与ParentEvent匹配的事件之后?在父事件1下面有一个ParentID为0的非常高兴的事件。@ErikE CID、NAME和ParentID是从表本身提交的,我刚刚更改了列的名称。只有深度列来自cte,在cte中,我刚刚计算了上面所有子记录的所有父记录-1,这是它在所需结果集中的显示方式。所需结果集显示ID顺序为0、2、4、1、3、5。您的查询显示ID顺序为0、1、2、3、4、5。这是不正确的。@ErikE问题文本:只要结果满足前两个条件,结果出现的顺序就不符合matterI的要求!请注意其中一个条件:具有非null ParentEvent的事件将直接出现在ID与ParentEvent匹配的事件之后。结果集中的行3“非常悲伤的事件”,1,1不是直接在其父事件1之后!这是如何满足条件的?问题文本:只要结果满足前两个条件,结果出现的顺序就不会改变matter@ErikE直到我发布了我的答案后,我才看到你的答案。你也有同样的想法,但在我之前就发布了。同样的varbinary转换可以完成,允许高达2000级的深度?8000/码发现了,但也许我弄错了,安德烈,这不是第一次,谢谢你让我保持警惕!请注意,您不需要先转换为int,而且varbinary2只允许ID值高达65535。@ErickE谢谢。你是对的。我删除了转换为int的命令。我意识到varbinary2是有限的,但我认为这对于这个例子来说是可行的。我最初有varbinary3,但它似乎有点过分了。
;WITH CTE
AS
(
  SELECT 
    ID, 
    NAME,
    ParentID,
    0 as Depth,
    convert(varbinary(max), convert(varbinary(2), ID)) as ThePath
  FROM   hierarchy
  WHERE ParentID is null

  UNION ALL

  SELECT 
    h.ID, 
    h.NAME,
    h.ParentID, 
    cte.Depth + 1,
    cte.ThePath + convert(varbinary(max), convert(varbinary(2), h.ID)) as ThePath
  FROM   hierarchy AS h 
  INNER JOIN CTE as cte
  ON h.ParentID = cte.ID
)
SELECT 
  ID, 
  NAME, 
  ParentID, 
  Depth, 
  ThePath
FROM CTE 
ORDER BY ThePath
ID          NAME                           ParentID    Depth       ThePath
----------- ------------------------------ ----------- ----------- ---------------
0           Happy Event                    NULL        0           0x0000
2           Very Happy Event               0           1           0x00000002
4           Happiest Event                 2           2           0x000000020004
1           Sad Event                      NULL        0           0x0001
3           Very Sad Event                 1           1           0x00010003
5           Unpleasant Event               1           1           0x00010005