Quantcast
Channel: SQLParty » with
Viewing all articles
Browse latest Browse all 2

怎样递归的查找最高层次的分类名称

$
0
0

我有这样一张表category,表结构和内容如下:

slno      category            uppercategory

1           Mouse              Computer
2          Computer            Electronics
3          Electronics           END
4           END                    -

上表可以很容易看出其含义。Mouse(鼠标)的上层分类为Computer(电脑),而Computer的上层分类为Electronics(电子产品),再上面不做分类了,就为END。该表记录了各种各样的分类,分类名称唯一,上例只是取了四条样例数据。

现在我的需求是,输入一个分类@Dcat,希望返回其顶层分类名称,即END之下的分类。我尝试了如下代码,但是不起作用:

USE [Database1]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[kt_category]
       @Dcat AS NVARCHAR(250)
AS
DECLARE @tmp TABLE (cater NVARCHAR(255))

BEGIN

INSERT INTO @tmp
SELECT UPPERCATEGORY FROM CATEGORY where CATEGORY=@Dcat

while( SELECT UPPERCATEGORY FROM CATEGORY )= 'END'
RETURN
END

这样的需求应该如何实现呢

本题来源stackoverflow

本题是典型的递归查询的应用,在Oracle/SQLServer/DB2中都支持使用with来实现递归。具体可以如下:
WITH R
     AS (SELECT *,
                1 AS Level
         FROM   CATEGORY
         WHERE  Category = @Dcat
         UNION ALL
         SELECT C.*,
                R.Level + 1
         FROM   CATEGORY C
                JOIN R
                  ON R.Uppercategory = C.Category)
SELECT *
FROM   R
WHERE Uppercategory  = 'End'

这里利用With生成了一张临时表。

临时表的生成过程是这样的:首先执行union all上部的SQL,对R进行初始化。基于这些初始化数据,再执行union all下部的SQL。执行过程中,依次取R中的每一条记录找出下部查询中的返回,再插入到R中,循环往复,直到union all下部SQL没有记录返回为止。R中记录的处理顺序是基于插入的先后顺序。当R表记录最终确定后,执行with后面的select。

上面给出的解答中,LEVEL其实可以不需要,它的作用是表示出递归的层次,这里也就是category从底向上的层数,可以帮助理解。LEVEL在本题来源中协助进行结果处理,详细见本题来源stackoverflow

在MySQL环境下,暂时没有类似With的递归处理方法,可以通过循环查询的方式变通,本次不做扩展。

The post 怎样递归的查找最高层次的分类名称 appeared first on SQLParty.


Viewing all articles
Browse latest Browse all 2

Trending Articles