[英]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,因此开始和结束都是一个简单的MIN
和MAX
。
棘手的部分是找出链中最后一行的ID。 有两种方法可以做到,两者都在查询中说明。 您可以使用递归表连接回来,在这种情况下,它将重新构建递归表,或者您可以尝试跟踪最后一个项目。 (如果构建链式记录的递归列表很昂贵,那么您肯定希望最大限度地减少需要执行此操作的次数。)
它跟踪的方式是跟踪它在链中的位置( level
列 - 注意我们每次递增时加1),零填充它,然后将ID粘贴在最后。 然后,获取具有最大level
的项目只是MAX
然后剥离level
数据。
如果CTE必须递归太多,它将产生错误,但我相信您可以使用MAXRECURSION
选项进行调整。 默认值为100.如果必须将其设置为高于此值,则可能需要考虑不使用递归CTE来执行此操作。
这也不能很好地处理格式错误的数据。 如果您有两个记录具有相同的first
或记录,其中first
== end
,那么这将无法正常工作,您可能必须调整CTE内的连接条件或采用其他方法。
这不是唯一的方法。 我相信如果您构建自定义过程并手动执行所有步骤,则会更容易理解。 但这具有在单一陈述中操作的优点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.