Сложный запрос на обновление на SQL Server - PullRequest
0 голосов
/ 28 августа 2018

У меня есть три таблицы:

  • Школа : SchoolID, SchoolName, город, штат, ...
  • Студент : StudentID, SchoolID (fk), Имя, Фамилия, Дата рождения, ...
  • StudentTest : StudentTestID, StudentID (fk), TestDate, Grade, ...

Иногда я знаю, что ученики переводятся в разные школы, и в этом случае я просто заменяю Student.SchoolID на новую SchoolID.

Часто я не узнаю, что ученик переведен, и в этом случае я получаю двух учеников с одинаковыми FirstName, LastName, Birthdate, но разными SchoolID. Я назову этих дублирующих студентов (индекс препятствует тому, чтобы все четыре поля были идентичными). Когда это происходит, мне нужно перейти к таблице StudentTest и изменить StudentTest.StudentID, чтобы соответствовать новому StudentID. После того, как все тесты переданы «новому» студенту, я могу удалить старую студенческую запись.

При очистке базы данных SQL Server с 35 000 учеников у меня дублируется 1600 учеников с различным количеством тестов, связанных с дублирующимися учениками.

Я могу выбрать тесты дубликатов студентов, чтобы они были сгруппированы вместе, взятые из вида (vwTestList, который объединяет некоторую информацию о студентах с тестовой информацией):

SELECT 
    a.SchoolID as SchID, a.StudentID as StudID, a.StudentTestID as TestID, 
    a.LastName as LName, a.FirstName as FName, 
    a.Birthdate as BDate, a.Testdate as Tdate, a.Grade
FROM 
    dbo.vwTestList a
JOIN 
    (SELECT 
         firstname, lastname, BirthDate, SchoolID
     FROM 
         dbo.vwTestList
     GROUP BY 
         firstname, lastname, BirthDate, SchoolID
     HAVING 
         COUNT(*) > 1) b ON a.firstname = b.firstname
                         AND a.lastname = b.lastname
                         AND a.BirthDate = b.BirthDate
                         AND a.SchoolID <> b.SchoolID
ORDER BY 
    a.LastName, a.FirstName, a.BirthDate, a.Testdate DESC

Пример результатов:

SchID   StudID  TestID LName    FName   Bdate       TDate      Grade
----------------------------------------------------------------------
461     16172   142773  Auk     Jay     2000-06-29  2010-04-13  4.7 
461     16172   136350  Auk     Jay     2000-06-29  2009-04-14  3.7 
146     5234    128517  Auk     Jay     2000-06-29  2008-04-01  2.7 
146     5234    123560  Auk     Jay     2000-06-29  2007-04-10  1.7

Однако я не могу выяснить запрос на обновление, который изменит все тесты для каждого набора дублирующих учащихся на StudentID самого последнего теста в наборе. В этом примере все тесты Джея Аука должны заканчиваться StudentID из 16172. Любая помощь будет оценена!

1 Ответ

0 голосов
/ 28 августа 2018

Посмотрите на следующий пример и посмотрите, поможет ли это вам начать. Этот пример можно запустить в SSMS.

-- replicate environment --

DECLARE @TestView TABLE (
    SchID INT, StudID INT, TestID INT, LName VARCHAR(30), FName VARCHAR(30), BDate DATETIME, TDate DATETIME, Grade DECIMAL(10,1)
)

INSERT INTO @TestView (
    SchID, StudID, TestID, LName, FName, BDate, TDate, Grade
)
VALUES
  ( 461, 16172, 142773, 'Auk', 'Jay', '2000-06-29', '2010-04-13', 4.7 )
, ( 461, 16172, 136350, 'Auk', 'Jay', '2000-06-29', '2009-04-14', 3.7 )
, ( 146, 5234, 128517, 'Auk', 'Jay', '2000-06-29', '2008-04-01', 2.7 )
, ( 146, 5234, 123560, 'Auk', 'Jay', '2000-06-29', '2007-04-10', 1.7 )
, ( 152, 17899, 123561, 'Gates', 'Bill', '1955-10-28', '2007-04-15', 4.7 )
, ( 152, 17899, 123562, 'Gates', 'Bill', '1955-10-28', '2007-04-14', 3.7 )
, ( 157, 5235, 123563, 'Gates', 'Bill', '1955-10-28', '2007-04-01', 2.7 )
, ( 157, 5235, 123564, 'Gates', 'Bill', '1955-10-28', '2007-04-10', 1.7 );

-- starting data --

SELECT * FROM @TestView;

Возвращает:

+-------+--------+--------+-------+-------+-------------------------+-------------------------+-------+
| SchID | StudID | TestID | LName | FName |          BDate          |          TDate          | Grade |
+-------+--------+--------+-------+-------+-------------------------+-------------------------+-------+
|   461 |  16172 | 142773 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2010-04-13 00:00:00.000 | 4.7   |
|   461 |  16172 | 136350 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2009-04-14 00:00:00.000 | 3.7   |
|   146 |   5234 | 128517 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2008-04-01 00:00:00.000 | 2.7   |
|   146 |   5234 | 123560 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2007-04-10 00:00:00.000 | 1.7   |
|   152 |  17899 | 123561 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-15 00:00:00.000 | 4.7   |
|   152 |  17899 | 123562 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-14 00:00:00.000 | 3.7   |
|   157 |   5235 | 123563 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-01 00:00:00.000 | 2.7   |
|   157 |   5235 | 123564 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-10 00:00:00.000 | 1.7   |
+-------+--------+--------+-------+-------+-------------------------+-------------------------+-------+

Вы можете увидеть начальные значения выше.

Продолжаем ...

-- update the StudID to the most recent test StudID for student --

UPDATE @TestView
SET
    StudID = Tests.MostRecentID
FROM @TestView vwTestList
CROSS APPLY (

    SELECT TOP 1 StudID AS MostRecentID FROM @TestView vw 
    WHERE 
        vw.LName = vwTestList.LName 
        AND vw.FName = vwTestList.FName 
    ORDER BY vw.TDate DESC

) AS Tests;

-- view results --

SELECT * FROM @TestView;

Возвращает:

+-------+--------+--------+-------+-------+-------------------------+-------------------------+-------+
| SchID | StudID | TestID | LName | FName |          BDate          |          TDate          | Grade |
+-------+--------+--------+-------+-------+-------------------------+-------------------------+-------+
|   461 |  16172 | 142773 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2010-04-13 00:00:00.000 | 4.7   |
|   461 |  16172 | 136350 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2009-04-14 00:00:00.000 | 3.7   |
|   146 |  16172 | 128517 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2008-04-01 00:00:00.000 | 2.7   |
|   146 |  16172 | 123560 | Auk   | Jay   | 2000-06-29 00:00:00.000 | 2007-04-10 00:00:00.000 | 1.7   |
|   152 |  17899 | 123561 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-15 00:00:00.000 | 4.7   |
|   152 |  17899 | 123562 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-14 00:00:00.000 | 3.7   |
|   157 |  17899 | 123563 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-01 00:00:00.000 | 2.7   |
|   157 |  17899 | 123564 | Gates | Bill  | 1955-10-28 00:00:00.000 | 2007-04-10 00:00:00.000 | 1.7   |
+-------+--------+--------+-------+-------+-------------------------+-------------------------+-------+

StudID был обновлен до последней версии Test StudID для каждой строки. Присоединение к имени заставляет меня нервничать, но если у вас нет другого уникального способа гарантировать студенческий матч (например, два студента имеют одно и то же имя), тогда может быть не так много других вариантов.

Как всегда, проверяйте свои данные перед тем, как запускать обновление, но это должно помочь вам начать работу.

...