Оператор обновления SQL Server на основе оператора Select с несколькими значениями

У меня есть оператор Select, который хорошо работает, создавая 7636 строк:

SELECT c.ClientId
    FROM   dbo.tblTreatment e
      JOIN dbo.tblProgramAssessment pa
    ON pa.TreatmentID = e.TreatmentId
      JOIN #Client c
    ON c.ClientId = e.ClientId
      LEFT JOIN dbo.tblCessationOfTreatment ct
    ON ct.TreatmentId = e.TreatmentId
      LEFT JOIN dbo.tblClientGP m
    ON m.ClientId = c.ClientId
    WHERE  e.IsOpen = 1 
    AND    e.IsDeleted = 0 
    AND    ct.CessationDate is null
    AND    c.IsDeceased = 0 

Я пытаюсь обновить эти 7636 строк, но вместо этого обновляются 7446 строк. По моему (ограниченному) пониманию, это, вероятно, как-то связано с clientid. Вот заявление об обновлении:

UPDATE 
    #Client
SET 
    ToMigrate = 1
    , OpenTreatmentEpisodes = 1
WHERE 
    clientid in
    (SELECT c.ClientId
    FROM   dbo.tblTreatment e
      JOIN dbo.tblProgramAssessment pa
    ON pa.TreatmentID = e.TreatmentId
      JOIN #Client c
    ON c.ClientId = e.ClientId
      LEFT JOIN dbo.tblCessationOfTreatment ct
    ON ct.TreatmentId = e.TreatmentId
      LEFT JOIN dbo.tblClientGP m
    ON m.ClientId = c.ClientId
    WHERE  e.IsOpen = 1 
    AND    e.IsDeleted = 0 
    AND    ct.CessationDate is null
    AND    c.IsDeceased = 0  
)

Если я изменю «IN» на «=», я получу сообщение об ошибке: Подзапрос вернул более 1 значения. Это не разрешено, когда подзапрос следует за =, !=, ‹, ‹= , >, >= или когда подзапрос используется как выражение. Заявление было прекращено.

1) Я не очень понимаю, почему есть разница в 7446 и 7636 строк. 2) Как я могу обновить только 7636 строк из оператора select?

Заранее спасибо!


person Mo_Dlg    schedule 05.02.2020    source источник
comment
Судя по вашим результатам, у вас есть повторяющиеся значения clientid в #Client.   -  person Nick    schedule 06.02.2020
comment
Дублирование значений clientid в #Client имеет смысл. Спасибо, @Nick! Тем не менее, как я могу написать SQL-запрос для обновления только 7637 строк на основе оператора select?   -  person Mo_Dlg    schedule 06.02.2020


Ответы (1)


Как прокомментировал Ник, вы, вероятно, продублировали clientid в таблице #Client. В результате некоторые элементы, возвращаемые вашим подзапросом IN, совпадают в нескольких строках внешнего запроса, что приводит к обновлению нежелательных строк.

Я думаю, что вы могли бы обойти это, используя возможности обновляемого CTE SQL Server. Это работает, превращая ваш SELECT запрос в CTE, а затем UPDATE непосредственно в CTE (обратите внимание, что для этого CTE должен возвращать столбцы, которые необходимо обновить).

WITH cte AS (
    SELECT c.ToMigrate, c.OpenTreatmentEpisodes
    FROM dbo.tblTreatment e
    INNER JOIN dbo.tblProgramAssessment pa ON pa.TreatmentID = e.TreatmentId
    INNER JOIN #Client c ON c.ClientId = e.ClientId
    LEFT JOIN dbo.tblCessationOfTreatment ct ON ct.TreatmentId = e.TreatmentId
    LEFT JOIN dbo.tblClientGP m ON m.ClientId = c.ClientId
    WHERE  
           e.IsOpen = 1 
           AND e.IsDeleted = 0 
           AND ct.CessationDate is null
           AND c.IsDeceased = 0 
)
UPDATE cte SET ToMigrate = 1, OpenTreatmentEpisodes = 1
person GMB    schedule 05.02.2020
comment
При выборе должны быть указаны @GMB, ToMigrate и OpenTreatmentEpisodes. Независимое выполнение оператора Select дает 7636 строк, выполнение оператора WITH cte AS (SELECT ..) UPDATE Set ToMigrate = 1, OpenTreatmentEpisodes = 1 дает 7446 строк. Если я изменю UPDATE cte Set ToMigrate = 1, OpenTreatmentEpisodes = 1 на SELECT * FROM CTE, это даст 7636 строк. Я понимаю вероятность дублирования clientid, поэтому я запустил это: SELECT COUNT(*),clientid FROM #Client, где OpenTreatmentEpisodes = 1 GROUP BY clientid HAVING COUNT(clientid) › 1 (7446 OpenTreatmentEpisodes=1), 0 строк. - person Mo_Dlg; 06.02.2020
comment
PS - простыми словами скрипт WITH cte выдает 7446 строк. - person Mo_Dlg; 06.02.2020