0

我制作了一个 MS Access db 应用程序,它工作正常。

当我想从 2007 年到 2010 年更改计算机和访问版本时。当我想查看查询结果时,它会显示错误。我可以更改我的查询还是其他错误?

我的查询:

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)) 
AND ((NOT Exists (SELECT *
              FROM Pracoval
              WHERE Os_udaje.id_os_udaje = Pracoval.id_os_udaje
              AND Kalendar.id_kalendar = Pracoval.id_kalendar))) 
AND ((NOT Exists (SELECT *
              FROM REZERVACIA 
              WHERE Kalendar.id_kalendar BETWEEN REZERVACIA.platnost_od AND REZERVACIA.platnost_do 
              AND Os_udaje.id_os_udaje = REZERVACIA.id_os_udaje))) 
AND ((NOT Exists (SELECT *
              FROM DOVOLENKA 
              WHERE Kalendar.id_kalendar BETWEEN DOVOLENKA.od AND DOVOLENKA.do 
              AND Os_udaje.id_os_udaje = DOVOLENKA.id_os_udaje)));

错误:

This expression is typed incorrectly, or it is too complex to be evaluated. For example, a numeric expression may contain too many complicated elements. Try simplifying the expression by assigning parts of the expression to variables. (Error 3071)
4

2 回答 2

1

关于这个查询在 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);
于 2012-09-04T23:57:33.557 回答
1

问题出在我的操作系统的设置中。我已将数据集格式化为带有空格的“1. 1. 2012”,并且我正在使用没有空格的访问格式“1.1.2012”。当我在 Windows 中更改日期格式时,所有开始工作正常。

于 2012-09-05T12:09:38.663 回答