zoukankan      html  css  js  c++  java
  • sqlserver 树形结构表查询 获取拼接结果

    树形表结构如下

    IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[dbo].[Test]') AND type IN ('U'))
        DROP TABLE [dbo].[Test]
    GO
    
    CREATE TABLE [dbo].[Test] (
      [Id] bigint  IDENTITY(1,1) NOT NULL,
      [TypeName] nvarchar(50) COLLATE Chinese_PRC_CI_AS  NOT NULL,
      [ParentId] bigint  NULL
    )
    GO
    
    -- ----------------------------
    -- Records of Test
    -- ----------------------------
    SET IDENTITY_INSERT [dbo].[Test] ON
    GO
    
    INSERT INTO [dbo].[Test] ([Id], [TypeName], [ParentId]) VALUES (N'1', N'生活常识', N'0')
    GO
    
    INSERT INTO [dbo].[Test] ([Id], [TypeName], [ParentId]) VALUES (N'2', N'生活', N'1')
    GO
    
    INSERT INTO [dbo].[Test] ([Id], [TypeName], [ParentId]) VALUES (N'3', N'常识', N'2')
    GO
    
    SET IDENTITY_INSERT [dbo].[Test] OFF
    GO
    表结构及数据

    需要实现的结果

     对于这种情况有三种解决方案:游标、循环、CTE

    一、游标、循环

    DECLARE @temp nvarchar(MAX)='',@pid bigint=3; 
    WHILE @pid<>0 
    BEGIN IF @temp='' 
        SELECT @temp=TypeName,@pid=ParentId 
        FROM [dbo].[Test] 
        WHERE Id=@pid; 
    ELSE 
        SELECT @temp=(TypeName+'->'+@temp),@pid=ParentId 
        FROM [dbo].[Test] 
        WHERE Id=@pid; 
    END; 
    SELECT @temp AS TypeName;

    二、CTE

    ;with Tree as
    (
    select * from [Test] where Id=3
    union all
    select a.* from [Test] a join Tree b on a.Id=b.ParentId
    ) 
    select stuff((select '->' + TypeName from Tree order by Id FOR XML PATH('')),1,5,'')

    CTE语法

    ;[ WITH [ ,n ] ] ::= 
    expression_name [ ( column_name [ ,n ] ) ] 
    AS 
    ( CTE_query_definition )

    在使用CTE时应注意如下几点: 
    1、CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。

    2、CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下

    ;with
    cte1 as
    (
        select * from table1 where name like 'abc%'
    ),
    cte2 as
    (
        select * from table2 where id > 20
    ),
    cte3 as
    (
        select * from table3 where price < 100
    )
    select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id

    3、如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了,如下

    --  table1是一个实际存在的表
    
    ;with
    table1 as
    (
        select * from persons where age < 30
    )
    select * from table1  --  使用了名为table1的公共表表达式
    select * from table1  --  使用了名为table1的数据表

    4、CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。

    5、不能在 CTE_query_definition 中使用以下子句: 
    (1)COMPUTE 或 COMPUTE BY 
    (2)ORDER BY(除非指定了 TOP 子句) 
    (3)INTO 
    (4)带有查询提示的 OPTION 子句 
    (5)FOR XML 
    (6)FOR BROWSE

     6、如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,

    参考链接 

  • 相关阅读:
    Spring进阶—如何用Java代码实现邮件发送(一)
    如何在Apache中使用PHP处理PHP文件
    最“高大上”的Spring测试:Spring Test
    【编程直播】来约吗?
    【PaPaPa】实现缓存决策
    【PaPaPa】系统架构搭建浅析
    【PaPaPa】集成B/S主流技术的MVC5项目
    【轮子狂魔】手把手教你自造Redis Client
    【轮子狂魔】抛弃IIS,打造个性的Web Server
    【轮子狂魔】抛弃IIS,向天借个HttpListener
  • 原文地址:https://www.cnblogs.com/GoCircle/p/9442387.html
Copyright © 2011-2022 走看看