1 sql foreign-keys primary-key
问题陈述:-
以下是我的表格 -
Employee (EmployeeId, EmployeeName, EmployeeCountry)
Training (TrainingCode, TrainingName, TrainingType, TrainingTeacher)
Outcome (EmployeeId, TrainingCode, Grade)
Run Code Online (Sandbox Code Playgroud)
该TrainingType字段指定训练类型,例如CASSANDRA,SQL等
以下是我为上述用例创建的表格.我不知道如何创建第三个表 - 结果?并EmployeeId, TrainingCode聚集在这里是一个主键?
CREATE TABLE employee
(
EmployeeId int,
EmployeeName varchar(255),
EmployeeCountry varchar(255),
PRIMARY KEY (EmployeeId)
);
CREATE TABLE Training
(
TrainingCode int,
TrainingName varchar(255),
TrainingType varchar(255),
TrainingTeacher varchar(255),
PRIMARY KEY (TrainingCode)
);
Run Code Online (Sandbox Code Playgroud)
简洁地说,是的:Outcome表中EmployeeID和TrainingCode的组合是主键.这些列中的每一列也分别是其他两个表之一的外键.因此:
CREATE TABLE Outcome
(
EmployeeId INT REFERENCES Employee,
TrainingCode INT REFERENCES Training,
Outcome VARCHAR(255),
PRIMARY KEY(EmployeeID, TrainingCode)
);
Run Code Online (Sandbox Code Playgroud)
您可能需要为您的特定DBMS提供其他一些词语,但要点应该清楚.
正如聊天会话中所讨论的,您需要使用TDQD - 测试驱动的查询设计 - 一次建立一个答案.我将假设至少有一个IT培训课程和至少一个商务培训课程.如果您必须确保每个员工都被选中,例如,如果没有IT课程(因为如果没有课程,每个员工都参加了所有可用的IT课程),那就非常棘手了.我也假设问题中的'或'是包容性OR,而不是排他性异或.
查找IT培训课程的数量.
SELECT COUNT(*) AS ITClassesAvailable
FROM Training
WHERE TrainingType = 'IT'
Run Code Online (Sandbox Code Playgroud)查找商务培训课程的数量.
SELECT COUNT(*) AS BusinessClassesAvailable
FROM Training
WHERE TrainingType = 'Business'
Run Code Online (Sandbox Code Playgroud)查找至少参加过一次IT培训课程的每位员工所参加的IT培训课程的数量.
SELECT O.EmployeeID, COUNT(*) AS NumberOfITCoursesTaken
FROM Outcome AS O
JOIN Training AS T ON O.TrainingCode = T.TrainingCode
WHERE T.TrainingType = 'IT'
Run Code Online (Sandbox Code Playgroud)查找至少参加过一次商务培训课程的每位员工所参加的商务培训课程的数量.
SELECT O.EmployeeID, COUNT(*) AS NumberOfBusinessCoursesTaken
FROM Outcome AS O
JOIN Training AS T ON O.TrainingCode = T.TrainingCode
WHERE T.TrainingType = 'Business'
Run Code Online (Sandbox Code Playgroud)找到参加过每个IT培训课程的员工.
SELECT X.EmployeeID
FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfITCoursesTaken
FROM Outcome AS O
JOIN Training AS T ON O.TrainingCode = T.TrainingCode
WHERE T.TrainingType = 'IT'
) AS X
JOIN (SELECT COUNT(*) AS ITClassesAvailable
FROM Training
WHERE TrainingType = 'IT'
) AS Y
ON X.NumberOfITCoursesTaken = Y.ITClassesAvailable
Run Code Online (Sandbox Code Playgroud)找到参加过每个商务培训课程的员工.
SELECT X.EmployeeID
FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfBusinessCoursesTaken
FROM Outcome AS O
JOIN Training AS T ON O.TrainingCode = T.TrainingCode
WHERE T.TrainingType = 'Business'
) AS X
JOIN (SELECT COUNT(*) AS BusinessClassesAvailable
FROM Training
WHERE TrainingType = 'Business'
) AS Y
ON X.NumberOfBusinessCoursesTaken = Y.BusinessClassesAvailable
Run Code Online (Sandbox Code Playgroud)因此,采用所有IT课程或所有商业课程的员工列表是这两个查询的UNION,或者:
SELECT X.EmployeeID
FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfITCoursesTaken
FROM Outcome AS O
JOIN Training AS T ON O.TrainingCode = T.TrainingCode
WHERE T.TrainingType = 'IT'
) AS X
JOIN (SELECT COUNT(*) AS ITClassesAvailable
FROM Training
WHERE TrainingType = 'IT'
) AS Y
ON X.NumberOfITCoursesTaken = Y.ITClassesAvailable
UNION
SELECT X.EmployeeID
FROM (SELECT O.EmployeeID, COUNT(*) AS NumberOfBusinessCoursesTaken
FROM Outcome AS O
JOIN Training AS T ON O.TrainingCode = T.TrainingCode
WHERE T.TrainingType = 'Business'
) AS X
JOIN (SELECT COUNT(*) AS BusinessClassesAvailable
FROM Training
WHERE TrainingType = 'Business'
) AS Y
ON X.NumberOfBusinessCoursesTaken = Y.BusinessClassesAvailable
Run Code Online (Sandbox Code Playgroud)
同时参加所有IT课程和所有商务课程的员工列表是两个查询的交集(使用INTERSECT代替UNION,或使用UNION查询的两半连接).
我不会一步一步地写出这样的查询; 我通常不会第一次得到它.但是你可以看到我采取的步骤,并测试每个组件查询,你可以检查它们(a)在语法上是否正确,以及(b)对你的测试数据产生正确的答案,从那里你可以看到如何组合组件查询以进行更复杂的查询和最终查询.并且,如果有必要,可以随时进行更正.这是TDQD的好处.