2008-08-20 65 views
3

我有一個視圖,其中包含作業列表,其中包含分配給他們的人員以及他們所處的階段等數據。我需要編寫一個存儲過程,以返回每個人每個階段有多少作業。我該如何做一個Upsert表格?

到目前爲止,我有這個(簡體):

DECLARE @ResultTable table 
(
    StaffName nvarchar(100), 
    Stage1Count int, 
    Stage2Count int 
) 

INSERT INTO @ResultTable (StaffName, Stage1Count) 
    SELECT StaffName, COUNT(*) FROM ViewJob 
    WHERE InStage1 = 1 
    GROUP BY StaffName 

INSERT INTO @ResultTable (StaffName, Stage2Count) 
    SELECT StaffName, COUNT(*) FROM ViewJob 
    WHERE InStage2 = 1 
    GROUP BY StaffName 

但問題是,行不合並。所以如果一個職員在stage1和stage2中有工作,那麼@ResultTable中有兩行。我真正想做的是更新該行(如果存在該職員)並插入新行(如果該行不存在)。

有誰知道如何做到這一點,或者可以建議一種不同的方法? 我真的想避免使用遊標迭代用戶列表(但這是我的回退選項)。

我使用的是SQL Server 2005中

編輯:@Lee:不幸的是,InStage1 = 1是一個簡化。它更像是WHERE DateStarted IS NOT NULL和DateFinished IS NULL。

編輯:@BCS:我喜歡先插入所有員工,所以我只需要每次都做一次更新。但我努力讓這些UPDATE語句正確。

回答

1

IIRC有某種「我國重複」(名稱可能是錯誤的)語法,可以讓你更新,如果一個行存在(MySQL的)

或者某種形式的:

INSERT INTO @ResultTable (StaffName, Stage1Count, Stage2Count) 
    SELECT StaffName,0,0 FROM ViewJob 
    GROUP BY StaffName 

UPDATE @ResultTable Stage1Count= (
    SELECT COUNT(*) AS count FROM ViewJob 
    WHERE InStage1 = 1 
    @ResultTable.StaffName = StaffName) 

UPDATE @ResultTable Stage2Count= (
    SELECT COUNT(*) AS count FROM ViewJob 
    WHERE InStage2 = 1 
    @ResultTable.StaffName = StaffName) 
+1

您提到的「一式兩份」是INSERT ...在DUPLICATE KEY UPDATE上,文檔位於:http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html – nickf 2008-10-14 02:16:11

1

要獲得真正的「upsert」類型的查詢,您需要使用if exists ...類型的東西,而這不幸意味着使用遊標。

但是,您可以運行兩個查詢,一個用於在存在現有行的情況下執行更新,然後插入新查詢。我認爲這種基於集合的方法會更好,除非你專門處理少量的行。

2

您可以檢查是否存在並使用相應的命令。我相信,這確實在後臺使用遊標,但它是最好的,你可能會得到:

IF (EXISTS (SELECT * FROM MyTable WHERE StaffName = @StaffName)) 
begin 
    UPDATE MyTable SET ... WHERE StaffName = @StaffName 
end 
else 
begin 
    INSERT MyTable ... 
end 

SQL2008有一個新的MERGE能力這是很酷,但它不是在2005年

3

其實,我認爲你做得比現在更困難。這段代碼不會適用於你想要做的事情嗎?

SELECT StaffName, SUM(InStage1) AS 'JobsAtStage1', SUM(InStage2) AS 'JobsAtStage2' 
    FROM ViewJob 
GROUP BY StaffName 
0

對結果表的以下查詢應該再次組合行。這是假設InStage1和InStage2從來都不是'1'。

select distinct(rt1.StaffName), rt2.Stage1Count, rt3.Stage2Count 
from @ResultTable rt1 
left join @ResultTable rt2 on rt1.StaffName=rt2.StaffName and rt2.Stage1Count is not null 
left join @ResultTable rt3 on rt1.StaffName=rt2.StaffName and rt3.Stage2Count is not null 
0

我設法讓它與BCS的答案的變體一起工作。它不會讓我使用表變量,所以我不得不做一個臨時表。

CREATE TABLE #ResultTable 
(
    StaffName nvarchar(100), 
    Stage1Count int, 
    Stage2Count int 
) 

INSERT INTO #ResultTable (StaffName) 
    SELECT StaffName FROM ViewJob 
    GROUP BY StaffName 

UPDATE #ResultTable SET 
    Stage1Count= (
    SELECT COUNT(*) FROM ViewJob V 
    WHERE InStage1 = 1 AND 
     V.StaffName = @ResultTable.StaffName COLLATE Latin1_General_CI_AS 
    GROUP BY V.StaffName), 
    Stage2Count= (
    SELECT COUNT(*) FROM ViewJob V 
    WHERE InStage2 = 1 AND 
     V.StaffName = @ResultTable.StaffName COLLATE Latin1_General_CI_AS 
    GROUP BY V.StaffName) 

SELECT StaffName, Stage1Count, Stage2Count FROM #ResultTable 

DROP TABLE #ResultTable