[英]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.