2011-08-20 25 views
1

我在創建一些SQL(對於SQL Server 2008)時遇到了一些麻煩。從現有表的分組子字符串創建新表

我是優先級排序,以逗號分隔的任務的任務表:

Id = 1, LongTaskName = "a,b,c" 
Id = 2, LongTaskName = "a,c" 
Id = 3, LongTaskName = "b,c" 
Id = 4, LongTaskName = "a" 
etc... 

我試圖建立一個新表,通過第一個任務組他們,包含ID:

GroupName: "a", TaskId: 1 
GroupName: "a", TaskId: 2 
GroupName: "a", TaskId: 4 
GroupName: "b", TaskId: 3 

這裏是天真的,緩慢的,LINQ代碼:

foreach(var t in Tasks) 
{ 
    var gt = new GroupedTasks(); 
    gt.TaskId = t.Id; 

    var firstWord = t.LongTaskName.Split(','); 
    if(firstWord.Count() > 0) 
    { 
     gt.GroupName = firstWord.First(); 
    } 
    else 
    { 
     gt.GroupName = t.LongTaskName; 
    } 
    GroupedTasks.InsertOnSubmit(gt); 
} 

我寫了一個SQL函數做STRI ng分裂:

create function fn_Split(
@String nvarchar (4000), 
@Delimiter nvarchar (10) 
) 
returns nvarchar(4000) 

begin 
declare @FirstComma int 

set @FirstComma = charindex(@Delimiter,@String) 
if(@FirstComma = 0) 
return @String 

return substring(@String, 0, @FirstComma) 
end 
go 

但是,我陷入了真正的SQL來做這項工作。 我可以獨自一人的羣組:

SELECT dbo.fn_Split(LongTaskName, ',') 
    FROM [dbo].[Tasks] 
    GROUP BY dbo.fn_Split(LongTaskName, ',') 

而且我知道我需要低着頭像這樣:

DECLARE @RowSet TABLE (GroupName nvarchar(1024), Id nvarchar(5)) 
insert into @RowSet 
select ??? 
FROM [dbo].Tasks as T 
INNER JOIN 
(
    SELECT dbo.fn_Split(LongTaskName, ',') 
     FROM [dbo].[Tasks] 
     GROUP BY dbo.fn_Split(LongTaskName, ',') 
) G 
ON T.??? = G.??? 
ORDER BY ??? 
INSERT INTO dbo.GroupedTasks(GroupName, Id) 
select * from @RowSet 

但我不太groking如何引用分組的關係,感到困惑關於不得不多次呼叫拆分。

有什麼想法?

回答

2

如果您只關心列表中的第一項,則不需要真正的函數。我會推薦這種方式。你也不需要任何臨時持有的@RowSet表變量。

INSERT dbo.GroupedTasks(GroupName, Id) 
SELECT 
    LEFT(LongTaskName, COALESCE(NULLIF(CHARINDEX(',', LongTaskName)-1, -1), 1024)), 
    Id 
FROM dbo.Tasks; 

這是更容易,如果任務是1個字符長,您可以使用LEFT(LongTaskName, 1)而不是醜陋SUBSTRING/CHARINDEX亂。但是我猜測你的任務名稱不是一個字符長(如果是這樣的話,你應該包含一些變化的數據,這樣其他人就不會對長度做出假設)。

現在請記住,每當插入,更新或刪除dbo.Tasks行時,您都必須執行類似操作以使dbo.GroupedTasks保持最新狀態。你打算如何保持這兩個表同步?

更重要的是,您應該考慮首先單獨存儲最高優先級的任務,或者使用計算列或在插入之前分隔出來。一起調用數據是你在應用程序代碼中用散列表和數組做的事情,但它在數據庫中幾乎沒有任何正面的屬性。您幾乎總是花費更多的時間和精力將數據分離出來,而不是通過將數據保存在一起而保存起來。這將完全否定第二張桌子的需要。

+0

哇,很好。問題實際上是彌補的。這是我正在處理的一次性導入問題的簡化版本,所以我不必重新運行它。但非常感謝你的出色答案,並指出了潛在的問題! – teleball

0

選擇ID,將(',',LongTaskName)拆分爲GroupName到TasksWithGroupInfo 這是否回答了您的問題?