Sql server sqlserver中Oracle的previor连接仿真

Sql server sqlserver中Oracle的previor连接仿真,sql-server,sql-server-2005,Sql Server,Sql Server 2005,如何在SQL Server 2000/2005/2008中获得Oracle的CONNECT BY Previor的功能?实现递归查询的SQL标准方法(例如由IBM DB2和实现)是WITH子句。请参阅将connectby转换为WITH(技术上是递归的CTE)的一个示例——这个示例适用于DB2,但我相信它也适用于SQL Server 编辑:显然,最初的querant需要一个特定的示例,下面是一个来自IBM站点的示例,我已经给出了它的URL。给出一张表格: CREATE TABLE emp(empi

如何在SQL Server 2000/2005/2008中获得Oracle的CONNECT BY Previor的功能?

实现递归查询的SQL标准方法(例如由IBM DB2和实现)是
WITH
子句。请参阅将
connectby
转换为
WITH
(技术上是递归的CTE)的一个示例——这个示例适用于DB2,但我相信它也适用于SQL Server

编辑:显然,最初的querant需要一个特定的示例,下面是一个来自IBM站点的示例,我已经给出了它的URL。给出一张表格:

CREATE TABLE emp(empid  INTEGER NOT NULL PRIMARY KEY,
                 name   VARCHAR(10),
                 salary DECIMAL(9, 2),
                 mgrid  INTEGER);
mgrid
引用员工经理的
empid
时,任务是获取直接或间接向
Joan
报告的所有人的姓名。在Oracle中,这是一个简单的连接:

SELECT name 
  FROM emp
  START WITH name = 'Joan'
  CONNECT BY PRIOR empid = mgrid
在SQL Server、IBM DB2或PostgreSQL 8.4(以及SQL标准中,值得一提的是;-)中,完全等效的解决方案是递归查询(更复杂的语法,但实际上更强大、更灵活):

Oracle的
START WITH
子句成为第一个嵌套的
SELECT
,它是递归的基本情况,与递归部分
结合,递归部分只是另一个
SELECT


SQL Server特定风格的
WITH
当然有文档记录,其中还提供了使用此关键字的指导原则和限制,以及一些示例。

我以前没有使用过connect,但快速搜索显示它用于树结构。在SQL Server中,您可以使用常用的表表达式来获得类似的功能。

@Alex Martelli
的答案非常好! 但它一次只对一个元素起作用(
其中name='Joan'
) 如果取出
WHERE
子句,查询将同时返回所有根行

我对我的情况做了一点修改,这样它就可以显示表格的整个树

表定义:

CREATE TABLE [dbo].[mar_categories] ( 
    [category]  int IDENTITY(1,1) NOT NULL,
    [name]      varchar(50) NOT NULL,
    [level]     int NOT NULL,
    [action]    int NOT NULL,
    [parent]    int NULL,
    CONSTRAINT [XPK_mar_categories] PRIMARY KEY([category])
)
level
字面上是类别的级别0:根,1:根之后的第一个级别,…)

以及查询:

WITH n(category, name, level, parent, concatenador) AS 
(
    SELECT category, name, level, parent, '('+CONVERT(VARCHAR (MAX), category)+' - '+CONVERT(VARCHAR (MAX), level)+')' as concatenador
    FROM mar_categories
    WHERE parent is null
        UNION ALL
    SELECT m.category, m.name, m.level, m.parent, n.concatenador+' * ('+CONVERT (VARCHAR (MAX), case when ISNULL(m.parent, 0) = 0 then 0 else m.category END)+' - '+CONVERT(VARCHAR (MAX), m.level)+')' as concatenador
    FROM mar_categories as m, n
    WHERE n.category = m.parent
)
SELECT distinct * FROM n ORDER BY concatenador asc
(您不需要连接
级别
字段,我这样做只是为了使其更具可读性)

此查询的答案应类似于:

我希望它能帮助别人


现在,我想知道如何在MySQL上做到这一点^^

请举例说明。例如,以一些国家和州为例,如印度——国家1——国家2澳大利亚——澳大利亚国家1——澳大利亚国家2我正在寻找确切的查询我在URL上指出的例子确实给出了确切的查询——当你只需点击链接时,将其复制到这里似乎毫无意义!)F部分是我一直在寻找的。有没有任何方法可以增加这个级别?请举例说明。例如,以一些国家和州为例,比如印度——州1——州2澳大利亚——澳大利亚州1——澳大利亚州2由于您似乎想了解更多详细信息,您必须告诉我们一些表结构数据以及您正在尝试做的事。如果你有一个现有的Oracle查询,那将是一个好的开始…@John,请参阅我在回答中发布的URL,--它显示了如何使用先前的作品进行连接(一种很好但Oracle专有的获取树结构的语法),以及如何使用(递归)公共表表达式(即with关键字)获得相同的效果(这是一个SQL标准,在IBM DB2、Microsoft SQL Server和8.4版的开源PostgreSQL引擎中实现)@Alex:谢谢,我看到了你的帖子并阅读了这篇文章。这篇文章写得很好,我也明白为什么Oracle用户可能会喜欢Oracle语法。我更喜欢标准语法,因为它更通用。我在修改代码时遇到了一个奇怪的问题,在分隔符和递归列上有一个不相同的数据类型……但它解决了问题,只定义了第一个一个明确的长度…感谢您的帮助!是否可以避免从字符串(
concatenador
)为get-tree-like结构构建路径(这样每个子叶的值就被其他元素分组在一起而没有孔)?Oracle
connect by
以这种方式免费构建。我不明白,
connect by
查询的全部目的不是为了让它提供
级别,而不是你。@SuperDoophero在我对我的回答作出评论时说:“(你不需要连接级别字段,我只是为了让它更可读)”
WITH n(category, name, level, parent, concatenador) AS 
(
    SELECT category, name, level, parent, '('+CONVERT(VARCHAR (MAX), category)+' - '+CONVERT(VARCHAR (MAX), level)+')' as concatenador
    FROM mar_categories
    WHERE parent is null
        UNION ALL
    SELECT m.category, m.name, m.level, m.parent, n.concatenador+' * ('+CONVERT (VARCHAR (MAX), case when ISNULL(m.parent, 0) = 0 then 0 else m.category END)+' - '+CONVERT(VARCHAR (MAX), m.level)+')' as concatenador
    FROM mar_categories as m, n
    WHERE n.category = m.parent
)
SELECT distinct * FROM n ORDER BY concatenador asc