繁体   English   中英

在sql server 2005中选择

[英]select in sql server 2005

我有一张桌子跟随:

ID  |  first  |  end
--------------------
a   |      1  |    3
b   |      3  |    8
c   |      8  |   10

我想选择以下内容:

 ID  |  first  |  end
---------------------
a-c  |      1  |   10   

但我不能这样做。 请! 帮我。 谢谢!

这对我有用:

SELECT MIN(t.id)+'-'+MAX(t.id) AS ID,
       MIN(t.[first]) AS first,
       MAX(t.[end]) AS [end]
  FROM dbo.YOUR_TABLE t

请注意不要为列名使用“end”之类的保留字

我相信你可以使用递归的Common Table Expression来做到这一点,特别是如果你不期望很长的记录链:

WITH Ancestors AS
(
    SELECT
        InitRow.[ID] AS [Ancestor],
        InitRow.[ID],
        InitRow.[first],
        InitRow.[end],
        0 AS [level],
        '00000' + InitRow.[ID] AS [hacky_level_plus_ID]
    FROM
        YOUR_TABLE AS InitRow
    WHERE
        NOT EXISTS
        (
            SELECT * FROM YOUR_TABLE AS PrevRow
            WHERE PrevRow.[end] = InitRow.[first]
        )
    UNION ALL
    SELECT
        ParentRow.Ancestor,
        ChildRow.[ID],
        ChildRow.[first],
        ChildRow.[end],
        ParentRow.level + 1 AS [level],
        -- Avoids having to build the recursive structure more than once.
        -- We know we will not be over 5 digits since CTEs have a recursion
        -- limit of 32767.
        RIGHT('00000' + CAST(ParentRow.level + 1 AS varchar(4)), 5)
            + ChildRow.[ID] AS [hacky_level_plus_ID]
    FROM
        Ancestors AS ParentRow
        INNER JOIN YOUR_TABLE AS ChildRow
            ON ChildRow.[first] = ParentRow.[end]
)
SELECT
    Ancestors.Ancestor + '-' + SUBSTRING(MAX([hacky_level_plus_ID]),6,10) AS [IDs],
-- Without the [hacky_level_plus_ID] column, you need to do it this way:
--  Ancestors.Ancestor + '-' +
--      (SELECT TOP 1 Children.ID FROM Ancestors AS Children
--      WHERE Children.[Ancestor] = Ancestors.[Ancestor]
--      ORDER BY Children.[level] DESC) AS [IDs],
    MIN(Ancestors.[first]) AS [first],
    MAX(Ancestors.[end]) AS [end]
FROM
    Ancestors
GROUP BY
    Ancestors.Ancestor
-- If needed, add OPTION (MAXRECURSION 32767)

快速解释每个部分的作用:

WITH Ancestors AS (...)子句创建一个名为Ancestors的公用表表达式(基本上是一个子查询)。 该表达式中的第一个SELECT建立一个基线:所有在它之前没有匹配条目的行。

然后,第二个SELECT是递归所在的位置。由于它将Ancestors作为查询的一部分引用,它使用已添加到表中的行,然后使用YOUR_TABLE新行执行连接。 这将以递归方式查找要添加到每个链末尾的越来越多的行。

最后一个子句是SELECT ,它使用我们构建的这个递归表。 它做了一个简单的GROUP BY因为我们已经在Ancestor列中保存了原始ID,因此开始和结束都是一个简单的MINMAX

棘手的部分是找出链中最后一行的ID。 有两种方法可以做到,两者都在查询中说明。 您可以使用递归表连接回来,在这种情况下,它将重新构建递归表,或者您可以尝试跟踪最后一个项目。 (如果构建链式记录的递归列表很昂贵,那么您肯定希望最大限度地减少需要执行此操作的次数。)

它跟踪的方式是跟踪它在链中的位置( level列 - 注意我们每次递增时加1),零填充它,然后将ID粘贴在最后。 然后,获取具有最大level的项目只是MAX然后剥离level数据。

如果CTE必须递归太多,它将产生错误,但我相信您可以使用MAXRECURSION选项进行调整。 默认值为100.如果必须将其设置为高于此值,则可能需要考虑不使用递归CTE来执行此操作。

这也不能很好地处理格式错误的数据。 如果您有两个记录具有相同的first或记录,其中first == end ,那么这将无法正常工作,您可能必须调整CTE内的连接条件或采用其他方法。

这不是唯一的方法。 我相信如果您构建自定义过程并手动执行所有步骤,则会更容易理解。 但这具有在单一陈述中操作的优点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM