Pergunta

Eu tenho uma visão que contém uma lista de empregos, com dados como a quem eles estão atribuídos e o estágio em que se encontram.Preciso escrever um procedimento armazenado que retorne quantos empregos cada pessoa possui em cada estágio.

Até agora eu tenho isso (simplificado):

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

O problema com isso é que as linhas não se combinam.Portanto, se um membro da equipe tiver empregos no estágio 1 e no estágio 2, haverá duas linhas em @ResultTable.O que eu realmente gostaria de fazer é atualizar a linha, se existir, para o membro da equipe e inserir uma nova linha, se não existir.

Alguém sabe como fazer isso ou pode sugerir uma abordagem diferente?Eu realmente gostaria de evitar o uso de cursores para iterar na lista de usuários (mas essa é minha opção alternativa).

Estou usando o SQL Server 2005.

Editar:@Lee: Infelizmente o InStage1 = 1 foi uma simplificação.É realmente mais parecido com WHERE DateStarted IS NOT NULL e DateFinished IS NULL.

Editar:@BCS: Gosto da ideia de fazer uma inserção de toda a equipe primeiro, então só tenho que fazer uma atualização sempre.Mas estou lutando para corrigir essas declarações UPDATE.

Foi útil?

Solução

IIRC existe algum tipo de sintaxe "On Duplicate" (o nome pode estar errado) que permite atualizar se existir uma linha (MySQL)

Alternativamente, alguma forma de:

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)

Outras dicas

Na verdade, acho que você está tornando tudo muito mais difícil do que é.Este código não funcionará para o que você está tentando fazer?

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

Você pode simplesmente verificar a existência e usar o comando apropriado.Acredito que isso realmente usa um cursor nos bastidores, mas é o melhor que você provavelmente obterá:

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

O SQL2008 tem um novo recurso MERGE que é legal, mas não está em 2005.

Para obter um tipo de consulta "upsert" real, você precisa usar um if exist...tipo de coisa, e isso infelizmente significa usar um cursor.

No entanto, você pode executar duas consultas, uma para fazer atualizações onde houver uma linha existente e depois inserir a nova.Eu acho que essa abordagem baseada em conjunto seria preferível, a menos que você esteja lidando exclusivamente com um pequeno número de linhas.

A consulta a seguir na sua tabela de resultados deve combinar as linhas novamente.Isso pressupõe que InStage1 e InStage2 nunca sejam '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

Consegui fazê-lo funcionar com uma variação da resposta do BCS.Porém, ele não me permitia usar uma variável de tabela, então tive que criar uma tabela temporária.

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top