【问题标题】:MS Access Left Join not working correctlyMS Access Left Join 无法正常工作
【发布时间】:2018-02-21 10:38:34
【问题描述】:

我正在尝试在 MS Access 2013 中编写查询,但左连接无法正常工作。它就像一个正常的连接。

这就是我想要做的。

我的第一个表 [All Category Types] 有一个列 [Category Types]。然后,我尝试将其加入到其中包含两个聚合字段的查询中。虚拟表[Average by Category Type]首先按所有者分组,然后按[Category Type]分组。接下来是一个总和字段[CountOfIncident: Number]

结果我想要的是表[All Category Types] 中的每个项目,然后是正确的[CountOfIncident: Number] where Owner == "France"。这不能用作左连接。它只向我显示[All Category Types] 中在[Average by Category Type] 中具有匹配记录的值。

如果我从这个表中删除所有者,并且只按[Category Type] 分组,它就可以正常工作。在 group by 子句中是否有多个字段不允许查询上的左连接正常工作?

SELECT [All Category Types].[Category Type], 
       [Average by Category Type].[CountOfIncident: Number]
FROM [All Category Types] 
LEFT JOIN [Average by Category Type] 
ON [All Category Types].[Category Type] = [Average by Category Type].[Category Type]
WHERE ((([Average by Category Type].Owner)="France"));

谢谢。

【问题讨论】:

  • 我的 5c:当列包含空格并且必须转义时,我发现查询的可读性较差。为什么不简单地SELECT all_category_types.category_type?当涉及多个表时,我还发现查询的可读性较差,但没有使用表别名(例如SELECT ct.category_type)。我还发现带有很多多余括号的查询可读性较差。为什么不简单地WHERE [Average by Category Type].Owner = "France"?最后,我宁愿尽可能使用标准 SQL。这将是字符串文字的单引号:= 'France'.
  • @philipxy 该副本是 MySQL,虽然原因相同,但 Access 在与常量连接时需要括号,这是造成混淆的常见原因,此处也进行了讨论。我认为这个问题足够明确。
  • @ErikA 这个问题被问了一遍又一遍。您是否在 Access 下搜索过它?此外,它不依赖于 SQL 的任何特定于 DBMS 的方面。这些解释通过吸引运营商的属性来明确这一点。所以它是重复的。

标签: sql ms-access ms-access-2013


【解决方案1】:

[Average by Category Type].Owner = "France" 只能用于内部连接记录。对于外部连接记录,[Average by Category Type].Owner 为空。

所以你的WHERE 子句将你的外连接变成了内连接。将条件移至ON 子句:

SELECT 
  [All Category Types].[Category Type], 
  [Average by Category Type].[CountOfIncident: Number]
FROM [All Category Types] 
LEFT JOIN [Average by Category Type] 
  ON ([Average by Category Type].[Category Type] = [All Category Types].[Category Type]
  AND [Average by Category Type].Owner = "France");

更新:与其他 DBMS MS Access 不同,ON 子句需要括号:JOIN tablename ON (...) 而不是 JOIN tablename ON ...

【讨论】:

  • 正要提出同样的建议。您可以将 WHERE 语句更改为 WHERE ((([Average by Category Type].Owner)="France")) OR [Average by Category Type].Owner IS NULL
  • @Erik von Asmuth:最好将条件移到它所属的ON 子句中。我已经相应地更新了我的答案。
  • 不适用于 MS Access。在ON 子句中进行此类比较往往会遇到麻烦(对于初学者来说,查询构建器将不再工作,但是当我这样做时查询失败(不支持 JOIN 表达式,Access 在其连接中很挑剔))。对于其他 RDBMS,你是对的。
  • 一次又一次,我很高兴,我不必使用 MS Access。很多年前我不得不这样做,由于它的所有局限性,这太可怕了。从我读到的内容来看,它似乎仍然是市场上最糟糕的 DBMS。
  • 请参阅 stackoverflow.com/questions/16608313/… 以了解按照您的意图执行连接但失败的问题,因为您无法在 Access 中执行此操作。
【解决方案2】:

Thorsten Kettner 的说法是正确的,即 WHERE 子句实质上将该语句变成了 INNER JOIN 的等价物。

使 LEFT JOIN 起作用的关键是了解应用标准的顺序。始终首先应用 JOIN 条件,然后在连接所有记录后应用 WHERE 子句。由于在 LEFT JOIN 中,无论是否满足连接条件,您都需要左表中的所有记录,因此您必须确保在应用之前或作为连接条件的一部分应用所有条件。

如果您可以得到 Thorsten 的答案以适用于连接中的所有条件,我建议您采用这种方法。但是,如果您有问题(很可能是 Access),那么您也可以在子查询中应用一些条件,或者在保存的查询中添加 WHERE 条件 [按类别类型平均]。也许很明显,但在上述关于执行顺序的解释的上下文中,子查询(包括 WHERE 子句中的任何过滤)在应用 LEFT JOIN 之前完成。

SELECT 
  [All Category Types].[Category Type], 
  AverageFiltered.[CountOfIncident: Number]
FROM [All Category Types] 
  LEFT JOIN 
    (SELECT * FROM [Average by Category Type] 
     WHERE [Average by Category Type].Owner = 'France')
    As AverageFiltered
  ON [All Category Types].[Category Type] = AverageFiltered.[Category Type];

【讨论】:

  • 我实际上可以获得 Thorsten Kettner 的答案的最新编辑,以处理示例数据库。也许删除关于他的问题的部分。
  • @ErikvonAsmuth 好吧,在这种情况下,我也让它工作了。但是,即使您与 Thorsten 的讨论也表明,使用 Access 通常很难使括号正确。在上个月,我不得不完全修改两个查询,因为括号的组合无法修复某些连接条件。由于这些答案不仅仅是为了原始提问者的利益,我认为引用其他答案是合理的。我给予他应有的信任并支持他的回答,但这种选择在其他情况下可能很关键。
  • 请注意,你总是可以走可怕的路:ON [Average by Category Type].[Category Type] = [All Category Types].[Category Type] AND [Average by Category Type].Owner = Right([All Category Types].[Category Type] & "France", 6) 工作正常,没有任何额外的括号
  • 这是我过去使用的技巧...我认为需要引用逻辑运算符两侧的表之一,但显然并非总是如此。我之前的问题是使用带日期的 Between 运算符进行连接。它工作得很好,没有问题,但后来我从查询中已经存在的表中向我的查询添加了 一个列,我认为另一个日期值......没有名称冲突,没有分组问题,没什么。突然间,我收到了重复的别名错误和不受支持的连接错误。除了使用带有子查询的基本连接之外,没有任何效果。
猜你喜欢
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
  • 2017-04-06
  • 2012-08-05
相关资源
最近更新 更多