关于这个查询在 Access 2007 中执行但在 Access 2010 中不是这样的事实:很难说为什么会出现这种情况,因为两者之间的大多数已发布差异都处理特定数据类型而不是允许 SQL 的规范句法。
正如其他评论所暗示的那样,我猜罪魁祸首在于AND NOT EXISTS (SELECT * FROM ...)
条件句。
话虽如此,我将提出一个等效的查询(理论上),以及提高其性能的技巧。
简化示例
首先,让我们解决这个查询试图使用单词完成的任务。Os_udaje
您正在寻找具有某些相关字段的表和的交叉连接(笛卡尔积),Kalendar
并删除在三个不同表中具有满足两个条件的相关记录的行。后一个要求是通过NOT EXISTS
子句来完成的,这就是我们要重写的。
举个例子:
SELECT TableA.Field1, TableB.Field2
FROM TableA, TableB WHERE
NOT EXISTS (SELECT *
FROM TableC
WHERE TableA.Field1=TableC.Field1
AND TableB.Field2=TableC.Field2);
无需详细说明原因,我们可以将此查询重写为具有一组不同WHERE
条件的三表交叉连接:
SELECT TableA.Field1, TableB.Field2
FROM TableA, TableB, TableC WHERE
(TableA.Field1=TableC.Field1)
AND
(TableB.Field2<>TableC.Field2);
完全等价查询
将此关系应用于原始查询,我们有:
SELECT Kalendar.id_kalendar, Os_udaje.Meno, Os_udaje.Priezvisko, Os_udaje.id_os_udaje
FROM Os_udaje, Kalendar, Pravocal, REZERVACIA, DOVOLENKA
WHERE ((((Kalendar.id_kalendar) Between [Pociatocný dátum] And [Koncový dátum])))
AND ((Kalendar.volno)=No)
AND ((Kalendar.vikend)=No)
AND (((Os_udaje.Nastupil)< Kalendar.id_kalendar ) AND ((Os_udaje.Odisiel)>Kalendar.id_kalendar))
AND (
Os_udaje.id_os_udaje = Pracoval.id_os_udaje
AND Kalendar.id_kalendar <> Pracoval.id_kalendar)
AND (
Kalendar.id_kalendar BETWEEN REZERVACIA.platnost_od AND REZERVACIA.platnost_do
AND Os_udaje.id_os_udaje <> REZERVACIA.id_os_udaje)
AND (
Kalendar.id_kalendar BETWEEN DOVOLENKA.od AND DOVOLENKA.do
AND Os_udaje.id_os_udaje <> DOVOLENKA.id_os_udaje);
提高性能的技巧
由于此查询执行 5 表交叉连接,因此效率可能非常低(取每个表中行数的乘积)。提高性能的两种技术是:
使用INNER JOIN
语句而不是完整的笛卡尔连接:
SELECT * FROM
(SELECT * FROM Table1,Table2) As SubQry
INNER JOIN
Table3
ON (SubQry.Field2=Table3.Field2 AND SubQry.Field1<>Table3.Field1);
首先执行子查询条件以减少行数:
SELECT Kalendar2.id_kalendar, Os_udaje.Meno, Os_udaje.Priezvisko, Os_udaje.id_os_udaje
FROM Os_udaje,
(SELECT * FROM Kalendar
WHERE ((((Kalendar.id_kalendar) Between [Pociatocný dátum] And [Koncový dátum])))
AND ((Kalendar.volno)=No)
AND ((Kalendar.vikend)=No)) AS Kalendar2,
Pravocal,
...
可能的完整答案
我无法测试这个查询,也不知道BETWEEN
语句是否可以作为JOIN
条件,但这里是使用连接和嵌套子查询的答案:
SELECT Kalendar.id_kalendar, Os_udaje.Meno, Os_udaje.Priezvisko, Os_udaje.id_os_udaje
FROM
(((
SELECT Kalendar.id_kalendar, Os_udaje.Meno, Os_udaje.Priezvisko, Os_udaje.id_os_udaje
FROM Os_udaje, Kalendar
WHERE ((((Kalendar.id_kalendar) Between [Pociatocný dátum] And [Koncový dátum])))
AND ((Kalendar.volno)=No)
AND ((Kalendar.vikend)=No)
AND (((Os_udaje.Nastupil)< Kalendar.id_kalendar ) AND ((Os_udaje.Odisiel)>Kalendar.id_kalendar))
) As SubQry
INNER JOIN
Pravocal
ON
(SubQry.id_os_udaje = Pracoval.id_os_udaje
AND SubQry.id_kalendar <> Pracoval.id_kalendar))
INNER JOIN
REZERVACIA
ON
(SubQry.id_kalendar BETWEEN REZERVACIA.platnost_od AND REZERVACIA.platnost_do
AND SubQry.id_os_udaje <> REZERVACIA.id_os_udaje))
INNER JOIN
DOVOLENKA
ON
(SubQry.id_kalendar BETWEEN DOVOLENKA.od AND DOVOLENKA.do
AND SubQry.id_os_udaje <> DOVOLENKA.id_os_udaje);