選擇我有一個表如下:在SQL Server 2005
ID | first | end
--------------------
a | 1 | 3
b | 3 | 8
c | 8 | 10
我想選擇如下:
ID | first | end
---------------------
a-c | 1 | 10
但我不能這樣做。請!幫我。謝謝!
選擇我有一個表如下:在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
但請,不要使用類似 「結束」 保留字列名。
我相信你可以做到這一點使用recursive 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內部的連接條件或採用其他方法。
這不是唯一的方法。我相信如果您構建自定義過程並手動完成所有步驟,將會更容易。但是這具有以單一語句操作的優點。
非常感謝你。你回答簡單嗎?我只使用小型數據庫。 – 2010-08-25 03:28:44
我明白了。但是我有一個表如下: ID第一端 b 3分配8 -C 8 10 d 15 19 E-10 12 F-19戰鬥機23 我認爲它假。 因爲我要選擇 ID第一端 一個-E 3.0 12 d-F 15 23 – 2010-08-24 03:42:33
@Vuong:我認爲,雖然,你可以擴展這一理念,以滿足您的需求。如果您將計算列添加到您的選擇中以生成分組標題(考慮使用'case'語句計算列),然後對計算進行分組,您仍然可以按照此處的建議應用「MIN」和「MAX」。 – kbrimington 2010-08-24 03:52:53
@Voung Mao:這是一個與你在問題中發佈的數據集不同的數據集 - 如果這是你處理的內容,你應該發佈這個問題的細節,因爲任何人都必須閱讀你的評論以瞭解其他標準。目前還不清楚你如何知道該數據集中有兩個組,或者他們開始和結束的位置。 – 2010-08-24 04:03:13