簡體   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