2014-06-06 47 views
0

我從分割查詢中有這個簡單的選擇。MS SQL:從分割字符串中選擇並保留原始順序

SELECT [id] 
FROM [user] WHERE [id] IN (
    SELECT items FROM dbo.Split('8004, 7943, 2658, 6223, 7826', ',') 
) 

的問題是,在用戶表中的select語句定購ID的上升,但我想保持原來的順序,該ID的出現在分割字符串函數。

這是我的分裂功能代碼:

ALTER FUNCTION [dbo].[Split](@String VARCHAR(8000), @Delimiter CHAR(1))  
RETURNS @temptable TABLE (items VARCHAR(8000))  
AS  
BEGIN  
DECLARE @idx INT  
DECLARE @slice VARCHAR(8000)  

SELECT @idx = 1  
    IF len(@String)<1 OR @String IS NULL RETURN  

WHILE @idx!= 0  
BEGIN  
    SET @idx = charindex(@Delimiter,@String)  
    IF @idx!=0  
     SET @slice = LEFT(@String,@idx - 1)  
    ELSE  
     SET @slice = @String  

    IF(LEN(@slice)>0) 
     INSERT INTO @temptable(Items) VALUES(@slice)  

    SET @String = RIGHT(@String,len(@String) - @idx)  
    IF LEN(@String) = 0 BREAK  
END 
RETURN  
END 

所以,我currenty得到的結果是:

2658 
6223 
7826 
7943 
8004 

我需要的是:

8004 
7943 
2658 
6223 
7826 

任何想法這是如何實現的?

謝謝!

+1

郵政代碼爲dbo.Split功能請 – user3036342

+0

沒關係,我看到問題:)給我一秒 – user3036342

+0

添加分割功能代碼 – squareOne

回答

0

重新寫入功能:

Create FUNCTION [dbo].[Split](@String VARCHAR(8000), @Delimiter CHAR(1))  
RETURNS @temptable TABLE (items VARCHAR(8000), rownum int)  
AS  
BEGIN  
DECLARE @idx INT  
DECLARE @slice VARCHAR(8000)  

SELECT @idx = 1  
    IF len(@String)<1 OR @String IS NULL RETURN  

WHILE @idx!= 0  
BEGIN  
    SET @idx = charindex(@Delimiter,@String)  
    IF @idx!=0  
     SET @slice = LEFT(@String,@idx - 1)  
    ELSE  
     SET @slice = @String  

    IF(LEN(@slice)>0) 
     INSERT INTO @temptable(Items) VALUES(@slice)  

    SET @String = RIGHT(@String,len(@String) - @idx)  
    IF LEN(@String) = 0 BREAK 

    --Added Rownumber here: 
    ;With CTE as 
    (
     Select Row_number() over (Order By (select 1)) as rownum 
     ,Items 
     FROM @temptable 
    )  
    Update T 
    set T.rownum = CTE.rownum 
    From @temptable T 
    JOIN CTE ON T.Items = CTE.Items 
END 
RETURN  
END 
Go 

,然後根據查詢:

SELECT U.[id] 
FROM [test_user] U 
Join (SELECT items,rownum FROM dbo.Split('8004, 7943, 2658, 6223, 7826', ',')) 
as T on T.items = U.id 
order by T.rownum asc 

檢查Demo這裏。

0

剛從dbo.Split程序將包含順序

N Value 
1 8004 
2 7943 
3 2658 

功能可能如下

CREATE FUNCTION [dbo].[Split](@String VARCHAR(8000), @Delimiter CHAR(1))  
RETURNS @temptable TABLE (N int, items VARCHAR(8000))  
AS  
BEGIN  
DECLARE @idx INT  
DECLARE @slice VARCHAR(8000) 
DECLARE @N int SET @N = 1 

SELECT @idx = 1  
    IF len(@String)<1 OR @String IS NULL RETURN  

WHILE @idx!= 0  
BEGIN  
    SET @idx = charindex(@Delimiter,@String)  
    IF @idx!=0  
     SET @slice = LEFT(@String,@idx - 1)  
    ELSE  
     SET @slice = @String  

    IF(LEN(@slice)>0) BEGIN 
     INSERT INTO @temptable(N, Items) VALUES(@N, @slice)  
     SET @N = @N + 1 
    END 

    SET @String = RIGHT(@String,len(@String) - @idx)  
    IF LEN(@String) = 0 BREAK  
END 
RETURN  
END 
GO 

或者你可能要返回附加字段(「N」爲例)用CTE版本替換拆分例程:

CREATE FUNCTION dbo.Split (@String varchar(8000), @Delimiter char(1)) 
RETURNS TABLE 
AS 
RETURN (
    WITH Splitter AS (
     SELECT 
     CHARINDEX(@Delimiter, @String) AS Pos, 
     0 AS LastPos, 
     1 AS N 
     UNION ALL SELECT 
     CHARINDEX(@Delimiter, @String, Pos + 1), 
     Pos, 
     N + 1 
     FROM 
     Splitter 
     WHERE 
     Pos > 0 
    ) 
    SELECT 
     N, 
     LTRIM(RTRIM(SUBSTRING(@String, LastPos + 1, CASE WHEN Pos = 0 then 80000 ELSE Pos - LastPos - 1 END))) AS items 
    FROM 
     Splitter 
) 
GO 

然後將您的查詢替換爲

SELECT 
    * 
FROM 
    [user] 
    INNER JOIN dbo.Split() AS [split] ON ([user].[id] = [split].[items]) 
ORDER BY 
    [split].[N] ASC 

更改dbo.Split更好,因爲不會影響現有代碼,但會給您可重複使用的解決方案。