【问题标题】:Access 2010 Strange behavior访问 2010 奇怪的行为
【发布时间】:2012-02-25 00:28:37
【问题描述】:

大家早上好,我在 Access 2010 中进行查询,我遇到了一个奇怪的行为,所以我想听听您的意见,我们开始吧:

SELECT X.*, L.CodLinea
FROM (
   SELECT TOP 1 'LBASE' AS CodLinea, 'Linea Base' AS Descrizione FROM ParametriAzienda
)  AS X LEFT JOIN Linee AS L 
ON X.CodLinea = L.CodLinea

内部查询总是给出一行,两列应该是这样的:

CodLinea  |  Descrizione
----------+--------------
  LBASE   |  Linea Base

现在,像上面那样进行左连接应该返回一个行和另一列 L.CodLinea,其值等于“LBASE”或 NULL,具体取决于表 Linee 内部是否有“LBASE”。所以,结果可以是:

  X.CodLinea  |  X.Descrizione  |  L.CodLinea
+-------------+-----------------+--------------+
    LBASE     |  Linea Base     |   LBASE      

如果值存在,或者

  X.CodLinea  |  X.Descrizione  |  L.CodLinea
+-------------+-----------------+--------------+
    LBASE     |  Linea Base     |   null      

如果该值不存在。事实上,我得到的是:

  X.CodLinea  |  X.Descrizione  |  L.CodLinea
+-------------+-----------------+--------------+
    LBASE     |  Linea Base     |   0          
    LBASE     |  Linea Base     |   0          
    LBASE     |  Linea Base     |   0          
    LBASE     |  Linea Base     |   0          
    LBASE     |  Linea Base     |   0          

这绝对不可能,因为:a) 我应该只得到一排; b) 0 不等于或不等于 LBASE。如果我使用 WHERE 而不是 LEFT JOIN(类似于 INNER JOIN)或 RIGHT JOIN,则结果是正确的(0 行)。

怎么回事?

编辑:实际上 ParametriAzienda 只有一行,并且 Linee 不包含 LBASE 值。

【问题讨论】:

  • 我还在 Jet 4.0 (.mdb) 上对此进行了测试,得到了相同的结果,即这对于 Access 2010 和 ACE (.accdb) 都没有问题。

标签: sql ms-access


【解决方案1】:

问题是TOP 1:要么你误解了它的用法(代码中的错误),要么是引擎中的错误。

就我个人而言,我总是使用DISTINCT,因为它是标准 SQL(并且我理解它的用途:)事实上,当我测试这个时,将 TOP 1 替换为 DISTINCT 会将您的实际结果变成预期结果。

这是我的复制品。下面的 VBA 在临时文件夹中创建一个新的数据文件,其中包含表格和示例数据。不需要参考,只需复制+粘贴到任何 VBA 模块,例如使用 Excel:

Sub NotTop1()

  On Error Resume Next
  Kill Environ$("temp") & "\DropMe.accdb"
  On Error GoTo 0

  Dim cat
  Set cat = CreateObject("ADOX.Catalog")

  With cat
  .Create _
        "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=" & _
        Environ$("temp") & "\DropMe.accdb"

    With .ActiveConnection

      Dim Sql As String

      Sql = _
      "CREATE TABLE ParametriAzienda (x INTEGER NOT NULL);"
      .Execute Sql

      Sql = _
      "INSERT INTO ParametriAzienda (x) VALUES (1);"
      .Execute Sql

      Sql = _
      "CREATE TABLE Linee (CodLinea CHAR(1) NOT NULL);"
      .Execute Sql

      Dim i As Long
      For i = 0 To 4
        Sql = _
        "INSERT INTO Linee (CodLinea) VALUES ('0');"
        .Execute Sql
      Next

      Sql = _
      "SELECT X.*, L.CodLinea " & _
      "FROM ( " & _
      "   SELECT TOP 1 'LBASE' AS CodLinea, 'Linea Base' AS Descrizione FROM ParametriAzienda " & _
      ")  AS X LEFT JOIN Linee AS L  " & _
      "ON X.CodLinea = L.CodLinea"

  Dim rs
  Set rs = .Execute(Sql)
  MsgBox rs.GetString(2, , vbTab & vbTab, , "<null>")

  Sql = Replace$(Sql, "TOP 1", "DISTINCT")

  Set rs = .Execute(Sql)
  MsgBox rs.GetString(2, , vbTab & vbTab, , "<null>")        
    End With
    Set .ActiveConnection = Nothing
  End With
End Sub

【讨论】:

  • 嗯,我想这不是问题所在。我们已经尝试不使用 TOP 1,但它仍然有 5 行,DISTINCT 也是如此。实际上,ParametriAzienda 只有一行...
  • @IssamTP:你试过运行我的代码吗?你得到不同的结果吗?如果没有,您能否更改我的代码以更好地反映您的情况?例如也许你的数据完全不同,你只是提供了它可能是什么的提示。
  • 我会告诉你的,我还添加了一些关于数据库数据的信息。
  • @IssamTP:注意我的数据已经满足你刚刚添加的条件(“ParametriAzienda 只有一行,Linee 不包含 LBASE 值”)。
  • 我已经测试了你的代码,而且,你是个天才,它可以工作。确实,当我第一次要求我的同事用 DISTINCT 更改 TOP 1 时,他误解了我,他将 DISTINCT 放在了外部查询中。
猜你喜欢
  • 1970-01-01
  • 2015-08-12
  • 2012-07-02
  • 2018-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多