3

我需要在 MS Access 中交叉多个子查询。不幸的是,Access-SQL 不支持 INTERSECT 关键字。我了解,我们如何使用两个表的 INNER JOIN 来获得我们想要的交集。但是我怎样才能以编程方式创建一个查询,使 N 个子查询相交呢?

更具体地说:我有一张员工表和一张专业化表。每个员工可以有多个专业化,这意味着员工和专业化之间存在多对多的关系,由一个包含员工和专业化 ID 的附加表表示,这并不复杂。

现在假设我想要一个员工列表,所有这些员工都在某处指定了所有专业。在任何其他 SQL 引擎中,我将简单地创建一个子查询列表并使用 INTERSECTION 关键字将这些子查询“连接”在一起,创建如下内容:

SELECT * FROM ( 
        (SELECT id, first_name, last_name FROM Employees JOIN Emp_spec 
            ON Employee.id = Emp_spec.spec_id WHERE Emp_spec.spec_id=x_1 )
        INTERSECT 
        ... 
        INTERSECT
        (SELECT id, first_name, last_name FROM Employees JOIN Emp_spec 
            ON Employee.id = Emp_spec.spec_id WHERE Emp_spec.spec_id=x_n )
);

,其中 x_1,...,x_n 表示对应于某些专业的一些 id。此查询返回一组员工,所有员工都具有所有特化 x_1,...,x_n。那么如何在没有 INTERSECT 关键字的 Access 中创建这样的查询。我一直在尝试使用 INNER JOIN 编写等效查询,但似乎无法成功。

4

2 回答 2

6

也许这就是你的想法。对于测试表 [员工] ...

id  first_name  last_name
--  ----------  ---------
 1  Gord        Thompson 
 2  Homer       Simpson  
 3  Hank        Kingsley 

...和 ​​[Emp_spec] ...

emp_id  spec_id
------  -------
     1        1
     1        2
     2        1
     3        1
     3        2

...查询

SELECT * FROM Employees
WHERE id IN (SELECT emp_id FROM Emp_spec WHERE spec_id=1)
    AND id IN (SELECT emp_id FROM Emp_spec WHERE spec_id=2)

返回

id  first_name  last_name
--  ----------  ---------
 1  Gord        Thompson 
 3  Hank        Kingsley 
于 2014-08-20T20:28:06.610 回答
0

如果你想用连接来做,你会为每个规范加入一个子查询,它只从 Emp_spec 中提取与单个 spec_id 匹配的行。注意 Access 对多个连接的奇怪的paren 要求。

SELECT Employees.id, Employees.first_name
FROM (Employees
INNER JOIN
    (SELECT employee_id
    FROM Emp_spec
    WHERE spec_id = x_1) specx_1
ON Employees.id = specx_1.employee_id)
INNER JOIN
    (SELECT employee_id
    FROM Emp_spec
    WHERE spec_id = x_2) specx_2
ON Employees.id = specx_2.employee_id
...

不过,您可以走捷径,但您可能会认为它太笨拙了。

SELECT Employees.id, Employees.first_name
FROM Employees
INNER JOIN
     (SELECT employee_id
     FROM Emp_spec
     WHERE spec_id IN (x_1, x_2, x_3, ..., x_n)
     GROUP BY employee_id
     HAVING COUNT(*) = n) match_counts
ON Employees.id = match_counts.spec_id

这里的关键部分是HAVING COUNT(*) = n. n当表被过滤为您想要的规范时,您只想获取在 Emp_spec 表中具有记录的员工,并且n您要过滤的规范数量在哪里。

于 2014-08-20T20:21:59.457 回答