简体   繁体   English

为MS-Access编写一个困难的查询(没有MINUS操作,3个表连接)

[英]Writing a difficult query for MS-Access (without MINUS operation, 3 table join)

I've come here for help with a complicated query. 我来这里寻求复杂查询的帮助。 I've tried a lot of different things for this and not quite got the results that I want. 我为此尝试了很多不同的东西,并没有得到我想要的结果。 A watered down version of my schema is as follows: The three tables in question are an Employees Table, an EmployeeTraining Table, and a RequiredTraining table. 我的模式的淡化版本如下:有问题的三个表是Employees表,EmployeeTraining表和RequiredTraining表。 The employees table holds information of an employee, such as empID,name, address, email, positionWorked, etc etc. The EmployeeTraining table holds an empID, and TrainingName.The RequiredTraining table has a Position and TrainingName. employees表包含员工的信息,例如empID,名称,地址,电子邮件,positionWorked等.EmployeeTraining表包含empID和TrainingName。RequiredTraining表具有Position和TrainingName。

Employees: empID , Name, Position 员工: empID ,姓名,职位

EmployeeTraining: empID , trainingName EmployeeTraining: empIDtrainingName

requiredTraining: Position , trainingName requiredTraining: 职位trainingName

Here's some sample data, just to further clarify: 以下是一些示例数据,仅用于进一步说明:

Employees 雇员

              *EMPID~~Name~~Position~~
                  1      Ted     Accountant

                  2      Bob     Janitor

employeeTraining 员工培训

                 **empID~~TrainingName**
                    1          Crunching Numbers

                    1          Microsoft Excel

                    1          Using an Abicus

                    2          Lemon Pledge 100

                    2          Scrubbing Toilets

requiredTraining requiredTraining

                  **position**~~**TrainingName**


                    Accountant    Crunching Numbers

                    Accountant    Microsoft Excel

                    Accountant    Using an Abicus

                    Accountant    TPS Reports

                    Janitor       Lemon Pledge 100

                    Janitor       Scrubbing Toilets

In english, and in the long run, I want to select an employee from a form and have a subform showing all of the training completed from that employee(SELECT * FROM Employees INNER JOIn EmployeeTraining on employees.empid = employeetraining.empID WHERE empID = me.empID) 在英语中,从长远来看,我想从一个表单中选择一个员工,并有一个子表单显示该员工完成的所有培训(SELECT * FROM Employees INNER JOE EmployeeTraining on employees.empid = employeetraining.empID WHERE empID = me.empID)

I also want another subform that shows the training that an employee has NOT completed that is required for their current position. 我还想要另一个子表单,其中显示员工尚未完成的培训,这是当前职位所必需的。 This is where I am struggling. 这是我在努力的地方。 I am not familiar or comfortable with using MS Access's query builder, but I have tried "find unmatched" queries as well as trying to write my own. 我对使用MS Access的查询构建器不熟悉或不熟悉,但我尝试过“查找无法匹配的”查询以及尝试编写自己的查询。 This seems like a MINUS operation would work, but MS Access doesn't support MINUS. 这似乎是MINUS操作可行,但MS Access不支持MINUS。 I have tried a LEFT JOIN with a null predicate as well as a NOT IN from the above query to a query of the requiredTraining table, but I haven't got the results I'm looking for. 我已尝试使用null谓词的LEFT JOIN以及上述查询中的NOT IN到requiredTraining表的查询,但我没有得到我正在寻找的结果。

For example, the result of the query I'm trying to write for this sample data would be: 例如,我试图为此示例数据编写的查询结果将是:

for employeeID 1 (Ted the Accountant) 对于employeeID 1(特别是会计师)

ted needs "TPS Reports" training 需要“TPS报告”培训

for employee 2 ( Bob the Janitor) 员工2(Bob the Janitor)

Bob has completed all of his training for his position. 鲍勃已完成他所有的职位培训。

An example of an attempted query I am trying is: 我正在尝试的尝试查询的示例是:

      SELECT employees.position,employeeTraining.empid,employeetraining.TrainingName          
      FROM EmployeeTraining 
      InNER JOIN Employees ON EmployeeTraining.empid = employees.empid
      WHERE empid = '1'
      LEFT JOIN
      SELECT TrainingName,Position FROM requiredTraining
      ON EmployeeTraining.Training = RequiredTraining.Training
      WHERE (((EmployeeTraining.Training is Null)))

Edit: This question has been answered. 编辑:这个问题已经回答了。 Thanks everyone for the help. 谢谢大家的帮助。 Your queries, although each was different, all accomplished the goal. 您的查询虽然各不相同,但都完成了目标。

The following query should return all employees with the training names that they need to complete: 以下查询应返回所有具有需要完成的培训名称的员工:

select e.emp_id, rt.TrainingName
from employees e left outer join
     RequiredTraining rt
     on e.position = rt.position
where rt.TrainingName not in (select TrainingName from EmployeeTraining et where et.empId = e.EmpId)

The join in the "from" clause finds all the required trainings. “from”子句中的联接可以找到所有必需的培训。 The "where" clause then uses a correlated subquery to find the ones the employee has not completed. 然后,“where”子句使用相关子查询来查找员工尚未完成的子查询。

you're very close actually, with your other query... you might try the NOT IN clause. 你实际上非常接近,你的其他查询...你可能会尝试NOT IN子句。 For example, as you have said, you can get all the employees that have completed a particular training like so: 例如,正如您所说,您可以获得完成特定培训的所有员工:

SELECT e.empID, e.name, e.Position, et.TrainingName
FROM Employees e
JOIN EmployeeTraining et ON e.empID = et.empID
WHERE empID = me.empID

What you want now, is all the employees that have NOT completed the training... you could just do a join on the trainingName table, making sure that the training type is not in the query you've already created, like so: 您现在想要的是,所有尚未完成培训的员工......您可以在trainingName表上进行联接,确保培训类型不在您已创建的查询中,如下所示:

SELECT e.empID, e.name, e.Position, rt.TrainingName
FROM Employees e
JOIN requiredTraining rt ON e.Position = rt.Position
WHERE rt.TrainingName NOT IN
(
   SELECT et.TrainingName
   FROM Employees e
   JOIN EmployeeTraining et ON e.empID = et.empID
   WHERE empID = me.empID
)
  AND e.empID = me.empID

Note that, as mentioned above, you don't actually need to join on the employees table... you could just use the following: 请注意,如上所述,您实际上不需要加入employees表...您可以使用以下内容:

SELECT e.empID, e.name, e.Position, rt.TrainingName
FROM Employees e
JOIN requiredTraining rt ON e.Position = rt.Position
WHERE rt.TrainingName NOT IN
(
   SELECT et.TrainingName
   FROM EmployeeTraining
   WHERE et.empID = me.empID
)
  AND e.empID = me.empID

The query below is created from two MS Access queries with the SQL cut and pasted into derived tables. 下面的查询是从两个MS Access查询创建的,其中SQL剪切并粘贴到派生表中。 The two queries select the employee with their current training (#1) and the employee with their required training (#2). 这两个查询选择具有当前培训的员工(#1)和具有所需培训的员工(#2)。 It is not updateable, but is easy to create. 它不可更新,但易于创建。 You can show only the missing training by adding a line at the end: 您可以通过在末尾添加一行来仅显示缺少的培训:

WHERE et.TrainingName Is Null

To select a single employee, you can add a line: 要选择单个员工,您可以添加一行:

WHERE rt.EMPID=1 AND et.TrainingName Is Null

However, you mention a subform, so I expect you will wish to use link child and master fields to limit by employee. 但是,您提到了一个子表单,因此我希望您希望使用链接子字段和主字段来限制员工。

SQL SQL

SELECT rt.empid,
       rt.position,
       rt.trainingname,
       et.trainingname AS IsTrained
FROM   (SELECT employees.empid,
               requiredtraining.position,
               requiredtraining.trainingname
        FROM   employees
               INNER JOIN requiredtraining
                       ON employees.position = requiredtraining.position) AS rt
       LEFT JOIN (SELECT employees.empid,
                         employees.position,
                         employeetraining.trainingname
                  FROM   employees
                         INNER JOIN employeetraining
                                 ON employees.empid = employeetraining.empid) AS
                 et
              ON ( rt.trainingname = et.trainingname )
                 AND ( rt.position = et.position )
                 AND ( rt.empid = et.empid ); 

The following query returns this result set based on your sample data as tested with Access 2007. 以下查询根据使用Access 2007测试的示例数据返回此结果集。

EMPID Position    TrainingName
1     Accountant  TPS Reports

SELECT
    sub.EMPID,
    sub.Position,
    sub.TrainingName
FROM
    (
        SELECT
            e.EMPID,
            e.Position,
            rt.TrainingName
        FROM
            Employees AS e
            INNER JOIN RequiredTraining AS rt
            ON e.Position = rt.position
    ) AS sub
    LEFT JOIN EmployeeTraining AS et
    ON
            sub.TrainingName = et.TrainingName
        AND sub.EMPID = et.empID
WHERE et.TrainingName Is Null;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM