1

问题陈述:-

下面是我的表-

Employee (EmployeeId, EmployeeName, EmployeeCountry)
Training   (TrainingCode, TrainingName, TrainingType, TrainingTeacher)
Outcome  (EmployeeId, TrainingCode, Grade)

TrainingType字段将训练类型指定为,例如CASSANDRASQL等。

下面是我为上述用例创建的表。我不确定如何创建第三个表 - 结果?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)
);
4

2 回答 2

5

简而言之,是的:Outcome 表中的 EmployeeID 和 TrainingCode 的组合是主键。这些列中的每一列也分别是其他两个表之一的外键。因此:

CREATE TABLE Outcome
(
    EmployeeId INT REFERENCES Employee,
    TrainingCode INT REFERENCES Training,
    Outcome VARCHAR(255),
    PRIMARY KEY(EmployeeID, TrainingCode)
);

对于您的特定 DBMS,您可能需要一些其他的词,但要点应该很清楚。


哪些员工参加了每门 IT 培训课程或每门业务培训课程?

正如聊天会话中所讨论的,您需要使用 TDQD(测试驱动的查询设计)一步一步地构建答案。我将假设至少有一门 IT 培训课程和至少一门商业培训课程。例如,如果您必须确保在 IT 课程为零的情况下选择每位员工(因为如果课程为零,则每位员工都参加了所有可用的 IT 课程),这将变得非常棘手。我还假设问题中的“或”是包容性 OR,而不是排他性 XOR。

  1. 查找 IT 培训课程的数量。

    SELECT COUNT(*) AS ITClassesAvailable
      FROM Training
     WHERE TrainingType = 'IT'
    
  2. 查找业务培训课程的数量。

    SELECT COUNT(*) AS BusinessClassesAvailable
      FROM Training
     WHERE TrainingType = 'Business'
    
  3. 找出每个参加过至少一门 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'
    
  4. 找出每个参加过至少一门商业培训课程的员工参加的商业培训课程的数量。

    SELECT O.EmployeeID, COUNT(*) AS NumberOfBusinessCoursesTaken
      FROM Outcome AS O
      JOIN Training AS T ON O.TrainingCode = T.TrainingCode
     WHERE T.TrainingType = 'Business'
    
  5. 查找参加过所有 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
    
  6. 查找参加过所有商务培训课程的员工。

    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
    
  7. 因此,参加过所有 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
    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
    

    参加过所有 IT 课程和所有商务课程的员工列表是这两个查询的交集(使用 INTERSECT 代替 UNION,或使用 UNION 查询的两半的连接)。

我不会一步一步写出这样的查询;我通常不会第一次做对。但是您可以看到我已采取的步骤,并测试每个组件查询,您可以检查它们 (a) 语法是否正确并且 (b) 在您的测试数据上产生正确的答案,从那里您可以看到如何组合组件查询以进行更复杂的查询以及最终查询。并且,如有必要,您可以随时进行更正。这就是 TDQD 的好处。

于 2013-09-21T03:36:35.777 回答
1

复合键可用于为结果表创建 PK。您需要在 Employee 和 Training 表上定义外键关系。

理想情况下,您会将结果表上的结果字段设置为非空字段。

CREATE TABLE Outcome
(
   EmployeeId INT REFERENCES Employee,  -- fk to table employee
   TrainingCode INT REFERENCES Training, -- fk to table training
   Outcome VARCHAR(255) not null,
   PRIMARY KEY(EmployeeID, TrainingCode) -- compound PK
);
于 2018-08-12T12:13:45.513 回答