SQL Server 2005: вставьте отсутствующие записи в таблицу, которая находится в другой справочной таблице - PullRequest
2 голосов
/ 07 сентября 2010

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

[Данные] Таблица

PersonId    Visit         Tested     Done
01          Day 1         Eyes       Yes
01          Day 1         Ears       Yes
01          Day 2         Eyes       Yes
01          Day 3         Eyes       Yes
02          Day 1         Eyes       Yes
02          Day 2         Ears       Yes
02          Day 2         Smell      Yes
03          Day 2         Eyes       Yes
03          Day 2         Smell      Yes
03          Day 3         Ears       Yes

, а вторая таблица содержит информацию о том, что необходимо проверить.

[Ref] Таблица

Visit      Test
Day 1      Eyes
Day 1      Ears
Day 1      Smell
Day 2      Eyes
Day 2      Ears
Day 2      Smell
Day 3      Eyes
Day 3      Ears
Day 3      Smell

сейчас я пытаюсь написать запрос вставки в [Data], чтобы вставить несуществующие тесты, которые необходимо было выполнить.Результат, который я ищу, например:

[Таблица данных] после:

PersonId    Visit         Tested     Done
01          Day 1         Eyes       Yes
01          Day 1         Ears       Yes
01          Day 1         Smell      No
01          Day 2         Eyes       Yes
01          Day 2         Ears       No
01          Day 2         Smell      No
01          Day 3         Eyes       Yes
01          Day 3         Ears       No
01          Day 3         Smell      No
02          Day 1         Eyes       Yes
02          Day 1         Ears       No
02          Day 1         Smell      No
02          Day 2         Eyes       No
02          Day 2         Ears       Yes
02          Day 2         Smell      Yes
02          Day 3         Eyes       No
02          Day 3         Ears       No
02          Day 3         Smell      No
03          Day 1         Eyes       No
03          Day 1         Ears       No
03          Day 1         Smell      No
03          Day 2         Eyes       Yes
03          Day 2         Ears       No
03          Day 2         Smell      Yes
03          Day 3         Eyes       No
03          Day 3         Ears       Yes
03          Day 3         Smell      No

При необходимости можно будет создать третью таблицу [результатов].Буду признателен за любую помощь.

С уважением, Жак

Ответы [ 5 ]

1 голос
/ 08 сентября 2010

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

INSERT INTO Results
(
    person_id,
    visit,
    tested,
    done
)
SELECT
    P.person_id,
    T.visit,
    T.test,
    'No'
FROM
    (SELECT DISTINCT person_id FROM Results) P -- Replace with Persons table if you have one
CROSS JOIN Templates T
LEFT OUTER JOIN Results R ON
    R.person_id = P.person_id AND
    R.visit = T.visit AND
    R.test = T.test
WHERE
    R.person_id IS NULL

Или альтернативно:

INSERT INTO Results
(
    person_id,
    visit,
    tested,
    done
)
SELECT
    P.person_id,
    T.visit,
    T.test,
    'No'
FROM
    (SELECT DISTINCT person_id FROM Results) P -- Replace with Persons table if you have one
INNER JOIN Templates T ON
    NOT EXISTS
    (
        SELECT *
        FROM
            Results R
        WHERE
            R.person_id = P.person_id AND
            R.visit = T.visit AND
            R.test = T.test
    )
0 голосов
/ 08 сентября 2010
INSERT Data
SELECT P.PersonID, R.Visit, D.Test, 'No'
FROM
   Person P -- or (SELECT DISTINCT PersonID FROM Data) P
   CROSS JOIN Ref R
WHERE
   NOT EXISTS (
      SELECT 1
      FROM Data D
      WHERE
         P.PersonID = D.PersonID
         AND R.Visit = D.Visit
         AND R.Test = D.Test
   )

И я не могу удержаться от публикации короткой версии ответа @ djacobson:

ALTER TABLE Data ADD CONSTRAINT DF_Data_Done DEFAULT ('No')

INSERT Data (PersonID, Visit, Test)
SELECT P.PersonID, R.Visit, D.Test
FROM Person P CROSS JOIN Ref R
EXCEPT SELECT PersonID, Visit, Test FROM Data
0 голосов
/ 08 сентября 2010

Вот, пожалуй, более простое решение с использованием Общих табличных выражений :

WITH allTestsForEveryone AS 
(
 SELECT *
 FROM (SELECT DISTINCT PersonID FROM DATA) a
 CROSS JOIN REF
),
allMissingTests AS 
(
 SELECT PersonID,Visit,Test FROM allTestsForEveryone
 EXCEPT
 SELECT PersonID,Visit,Tested FROM DATA
)
INSERT INTO [DATA] (PersonID, Visit, Tested, Done)
SELECT PersonID, Visit, Test, 0 AS Done FROM allMissingTests;

Первый CTE (allTestsForEveryone) дает вам набор всех тестов, необходимых во все дни для всех людей.Во втором CTE (allMissingTests) мы вычитаем тесты, которые имеют , с использованием оператора EXCEPT, и добавляем '0', чтобы представить их состояние "не выполнено", когда мы их вставляем (вы можете заменитьчто с «Нет» - когда я запускал этот тест, я использовал столбец bit).Затем мы вставляем результаты второго CTE в Data.

0 голосов
/ 08 сентября 2010

Это, вероятно, не лучший способ, но .... Что, если бы вы создали первичный ключ в таблице [Data],

PK: (PersonID, Visit, Tested)

Тогда вы могли бы создать функцию для вставкидля каждого personID и дня

CREATE PROCEDURE InsertTests
@PersonID int
, @Day nvarchar(10)

Begin

BEGIN TRY
INSERT INTO [Data]
(PersonID, Visit, Tested, Done)
VALUES
(@PersonID, @Day, Eyes, No)
END TRY
BEGIN CATCH
END CATCH

BEGIN TRY
INSERT INTO [Data]
(PersonID, Visit, Tested, Done)
VALUES
(@PersonID, @Day, Ears, No)
END TRY
BEGIN CATCH
END CATCH

BEGIN TRY
INSERT INTO [Data]
(PersonID, Visit, Tested, Done)
VALUES
(@PersonID, @Day, Smell, No)
END TRY
BEGIN CATCH
END CATCH

End
0 голосов
/ 08 сентября 2010

Я думаю, что вам понадобится таблица person только с идентификаторами personID, тогда вы можете выполнить перекрестное соединение (полное внешнее объединение) со своей таблицей ref test, чтобы составить расписание personIDs и ожидаемых тестов.

Затем, с этим установленным расписанием, выполните внешнее объединение с набором тестов, выполненных для personID, и ожидайте нулевые значения вместо no.

Затем, если хотите, вы можете преобразовать свои нули в 'нет'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...