Domanda

Ho una vista che contiene un elenco di lavori, con dati come a chi sono assegnati e la fase in cui si trovano.Devo scrivere una procedura memorizzata che restituisca quanti lavori ha ciascuna persona in ogni fase.

Finora ho questo (semplificato):

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

Il problema è che le righe non si combinano.Pertanto, se un membro dello staff ha lavori in stage1 e stage2, ci sono due righe in @ResultTable.Quello che mi piacerebbe davvero fare è aggiornare la riga se ne esiste una per il membro dello staff e inserire una nuova riga se non ne esiste una.

Qualcuno sa come farlo o può suggerire un approccio diverso?Vorrei davvero evitare di utilizzare i cursori per scorrere l'elenco degli utenti (ma questa è la mia opzione di riserva).

Sto utilizzando SQL Server 2005.

Modificare:@Lee: Sfortunatamente InStage1 = 1 era una semplificazione.In realtà è più simile a DOVE DateStarted IS NULL e DateFinish IS NULL.

Modificare:@BCS: Mi piace l'idea di fare prima un inserto di tutto lo staff, quindi devo solo fare un aggiornamento ogni volta.Ma faccio fatica a ottenere quelle dichiarazioni UPDATE corrette.

È stato utile?

Soluzione

IIRC esiste una sorta di sintassi "On Duplicate" (il nome potrebbe essere sbagliato) che ti consente di aggiornare se esiste una riga (MySQL)

In alternativa una qualche forma di:

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)

Altri suggerimenti

In realtà, penso che tu stia rendendo le cose molto più difficili di quanto non siano.Questo codice non funzionerà per quello che stai cercando di fare?

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

Potresti semplicemente verificarne l'esistenza e utilizzare il comando appropriato.Credo che questo utilizzi davvero un cursore dietro le quinte, ma è il meglio che probabilmente otterrai:

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

SQL2008 ha una nuova funzionalità MERGE che è interessante, ma non è nel 2005.

Per ottenere un vero tipo di query "upsert" è necessario utilizzare un se esiste...genere di cose, e questo sfortunatamente significa usare un cursore.

Tuttavia, potresti eseguire due query, una per eseguire gli aggiornamenti dove è presente una riga esistente, quindi successivamente inserire quella nuova.Penso che questo approccio basato su set sarebbe preferibile a meno che tu non abbia a che fare esclusivamente con un numero limitato di righe.

La seguente query sulla tabella dei risultati dovrebbe combinare nuovamente le righe.Ciò presuppone che InStage1 e InStage2 non siano mai entrambi "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

Sono riuscito a farlo funzionare con una variazione della risposta di BCS.Tuttavia non mi permetteva di usare una variabile di tabella, quindi ho dovuto creare una tabella temporanea.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top