Вопрос

У меня есть представление, в котором есть список заданий с такими данными, как, кому они назначены, и на каком этапе они находятся.Мне нужно написать хранимую процедуру, которая возвращает, сколько заданий у каждого человека есть на каждом этапе.

Пока у меня есть это (упрощенное):

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

Проблема в том, что строки не объединяются.Таким образом, если у сотрудника есть задания на этапах 1 и 2, в @ResultTable есть две строки.Что я действительно хотел бы сделать, так это обновить строку, если таковая существует для сотрудника, и вставить новую строку, если таковая не существует.

Кто-нибудь знает, как это сделать, или может предложить другой подход?Я бы действительно хотел избежать использования курсоров для итерации по списку пользователей (но это мой запасной вариант).

Я использую SQL Server 2005.

Редактировать:@Ли: К сожалению, InStage1 = 1 было упрощением.Это действительно больше похоже на то, ГДЕ dateStarted НЕ РАВНО NULL, а DateFinished РАВНО NULL.

Редактировать:@BCS: Мне нравится идея сначала сделать вставку всех сотрудников, поэтому мне просто нужно каждый раз делать обновление.Но я изо всех сил пытаюсь исправить эти инструкции по обновлению.

Это было полезно?

Решение

IIRC существует какой-то синтаксис "On Duplicate" (имя может быть неправильным), который позволяет обновлять, если строка существует (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)

Другие советы

На самом деле, я думаю, что ты делаешь это намного сложнее, чем есть на самом деле.Разве этот код не будет работать для того, что вы пытаетесь сделать?

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

Вы могли бы просто проверить наличие и использовать соответствующую команду.Я считаю, что здесь действительно используется курсор за кулисами, но это лучшее, что вы, скорее всего, получите:

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

В SQL2008 появилась новая возможность СЛИЯНИЯ, которая классная, но ее нет в 2005 году.

Чтобы получить реальный запрос типа "upsert", вам нужно использовать if exists...что-то в этом роде, и это, к сожалению, означает использование курсора.

Однако вы могли бы выполнить два запроса, один для выполнения ваших обновлений там, где есть существующая строка, а затем вставить новую.Я бы подумал, что такой подход, основанный на множествах, был бы предпочтительнее, если только вы не имеете дело исключительно с небольшим количеством строк.

Следующий запрос в вашей таблице результатов должен снова объединить строки.Это предполагает, что 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

Мне удалось заставить это работать с вариацией ответа 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top