我需要以下帮助。我有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
并且第二个表格包含需要测试的内容。
[参考]表
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
如果需要,可以创建第三个[results]表。 非常感谢所有帮助。
亲切的问候 雅克
答案 0 :(得分:1)
我怀疑数据库设计是否需要这个(以及其他一些红色标志),但以下查询应该能满足您的要求:
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
)
答案 1 :(得分:0)
我认为你需要一个只有personID的人员表,然后你可以用你的测试参考表进行交叉连接(完全外连接),以得出personID和预期测试的时间表。
然后,使用该计划集,使用在personID上执行的测试集进行外部联接,并期望空值而不是no。
然后,如果需要,可以将空值转换为“否”。
答案 2 :(得分:0)
这可能不是最好的方法,但是......如果你要在[数据]表上创建主键怎么办,
PK: (PersonID, Visit, Tested)
然后你可以创建一个为每个personID和Day
插入的函数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
答案 3 :(得分:0)
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
。
答案 4 :(得分:0)
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