【问题标题】:SQL database query grouping results by ChildrenIDs as well as subChildrenIDsSQL 数据库查询按 ChildrenID 和 subChildrenID 分组结果
【发布时间】:2020-01-20 23:06:33
【问题描述】:

我在 SQL Server 2008 中有这个 [Folders] 表:

TABLE [dbo].[Folders]
(
    [FolderID] [NUMERIC](18, 0) IDENTITY(1,1) NOT NULL,
    [SubFolderOf] [NUMERIC](18, 0) NOT NULL,
    [FolderName] [VARCHAR](128) NOT NULL
)

这是该表中的数据

[ID]  [SubFolderOf] [FolderName]
------------------------------------------------
1      0             Main [ROOT]
2      1             Technical And Development
3      1             Sales and Marketing
4      1             Legal
5      1             Finance
6      1             Departments
7      1             Compliance
8      2             Test Scripts
9      2             Documentation
10     2             Files
11     8             AV Training
12     8             AV Finance 1

[SubFolderOf] 列是 [ID] 列的子列。

例如,请注意 ID#12 (AV Finance 1) 是 ID#8 (Test Scripts) 的子文件夹,ID#8 (Test Scripts) 是 ID#2 (Technical and Development) 的子文件夹。

我无法编写返回以下结果的查询

[ID]  [Field Name]
----------------------------------------------------------
1     Main
2     Main >> Technical and Development
11    Main >> Technical and Development >> AV Training
12    Main >> Technical and Development >> AV Finance 1
3     Main >> Sales and Marketing
4     Main >> Legal

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 很高兴看到您的尝试。
  • 到目前为止你有什么尝试???
  • 感谢您的提问。我根本没有尝试太多的知识。我现在才学习加入。 @John-Capelletti 正是我在下面寻找的东西。我将对其进行剖析并从中学习。

标签: sql sql-server database sql-server-2008


【解决方案1】:

不清楚您是否跳过了所需结果的级别,但您似乎正在寻找递归 CTE。我很确定这与 2008 兼容。

示例

Declare @YourTable Table ([ID] int,[SubFolderOf] int,[FolderName] varchar(50))
Insert Into @YourTable Values 
 (1,0,'Main [ROOT]')
,(2,1,'Technical And Development')
,(3,1,'Sales and Marketing')
,(4,1,'Legal')
,(5,1,'Finance')
,(6,1,'Departments')
,(7,1,'Compliance')
,(8,2,'Test Scripts')
,(9,2,'Documentation')
,(10,2,'Files')
,(11,8,'AV Training')
,(12,8,'AV Finance 1')

Declare @Nest   varchar(25) = '|-----'  --<<  Optional: Added for readability

;with cteP as (
      Select Seq  = cast(10000+Row_Number() over (Order by ID) as varchar(500))
            ,ID
            ,SubFolderOf 
            ,Lvl=1
            ,FolderName 
            ,Path = cast(FolderName as varchar(500))
      From   @YourTable 
      Where  [SubFolderOf]=0
      Union  All
      Select Seq  = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.ID)) as varchar(500))
            ,r.ID
            ,r.SubFolderOf 
            ,p.Lvl+1
            ,r.FolderName 
            ,cast(p.path + ' >> '+r.FolderName as varchar(500))
      From   @YourTable r
      Join   cteP p on r.SubFolderOf  = p.ID)
Select A.ID
      ,A.SubFolderOf 
      ,A.Lvl
      ,FolderName = Replicate(@Nest,A.Lvl-1) + A.FolderName
      ,Path
 From cteP A
 Order By Seq

退货

【讨论】:

  • 这太棒了!它是动态的,因此我可以根据需要添加尽可能多的子文​​件夹 >> 子文件夹 >> 子文件夹。里面有很多我不熟悉的关键字,所以除了这个可以立即使用之外,还有很多新东西要我学习。谢谢你!
  • @Gregbert Alwats 乐于提供帮助
【解决方案2】:

您有几个选择,您可以多次自联接表(左联接),也可以使用“循环 cte”,这是一个常见的表表达式。我发现自加入更容易使用。您需要定义最多可以拥有多少次或级别,例如3 级深,5 或 10 级。

类似这样的:

select F.FolderId, concat(isnull(F3.FolderName, “”), “>>”, isnull(F2.FolderName, “”), “>>”, F.FolderName) as [Field name] from Folders as F
left join Folders as F2 on F2.FolderId = F.SubFolderOf
left join Folders as F3 on F3.FolderId = F2.SubFolderOf

您可以通过例如使用case 表达式或类似的表达式来消除多余的“>>”。

【讨论】:

  • 这种方式不会直接输出父文件夹的特殊情况。
  • @avery_larry 是的,因为我的 concat,它会的
猜你喜欢
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多