4

我有一个 Access 数据库,可以跟踪工厂车间的机器。我正在使用两个表:

  1. marstable- 每台机器已完成的操作列表
  2. statustable- 机器状态更改列表

marstable其中大约有 100,000 个条目,而statustable少于 100 个。

我需要一次查找一台机器才能找到以下三件事之一:

  1. 如果机器在两个表中都有条目,则返回两个表中的数据。
  2. 如果机器只有 中的条目 marstable,则返回该表中的数据。
  3. 如果机器只有 中的条目 statustable,则返回该条目中的数据。

如何执行 SQL 查询来完成此操作? 现在,使用左连接,除了在statustable(左连接的“右”部分)中只有数据的情况下,它可以工作。

marstable是按时间顺序排列的交易列表,如下所示:

+--------+----------+-----------+----------+-----------------------+
| order  | machine  | operation | quantity |      insertdate       |
+--------+----------+-----------+----------+-----------------------+
|  12345 | A10      |       110 |     2339 | 11/16/2012 9:57:15 AM |
|  67890 | B11      |       450 |    10330 | 11/16/2012 9:15:03 AM |
+--------+----------+-----------+----------+-----------------------+

statustable是按时间顺序排列的机器状态变化列表。看起来像:

+---------+--------+-----------------------+--------+
| machine | status |      inserttime       |  note  |
+---------+--------+-----------------------+--------+
| A10     |      6 | 11/5/2012 10:52:22 AM | broken |
| J90     |      7 | 11/9/2012 12:48:46 PM | robot  |
+---------+--------+-----------------------+--------+

我使用的 SQL 查询如下所示:

SELECT TOP 1 [machine], [quantity], [order], [operation], [insertdate], [status], [inserttime], [note]
FROM [marstable] LEFT JOIN [statustable] ON [marstable].[machine] = [statustable].[machine]
WHERE [marstable].[machine] = '<<machine I want get's passed in here>>'
ORDER BY [marstable].[insertdate] DESC, [statustable].[inserttime] DESC

问题是,当 中不存在条目marstable但 中有一个时statustable我仍然什么也得不到。

提前感谢您的帮助。此外,我无法控制表格的外观。

最后,请原谅我对上述表格缺乏 ascii-art Skillz。

更新#1:

我正在尝试从他下面的一个答案中实现@Olivier 的子查询解决方案。但是,当我这样做时,我得到一个错误 too few parameters. Expected 2.

我的实现与他的不同之处在于我将机器 ID 传递给生成 SQL 的函数,而不是请求参数。

SQL 是这样生成的

MarsSQL = _
    "SELECT M.msg_machine, M.msg_qtyorstatus, M.msg_entity, M.msg_operation, M.msg_creator, M.msg_insertdate, " & _
        "S.Machine, S.Status, S.InsertTime, S.Note, S.UserID " & _
    "FROM " & _
        "(SELECT TOP 1 msg_machine, msg_qtyorstatus, msg_entity, msg_operation, msg_creator " & _
        "FROM MARSTable WHERE msg_machine = '" & "00" & fMachine & "' ORDER BY msg_insertdate DESC" & _
        ") M, " & _
        "(SELECT TOP 1 Machine, Status, InsertTime, Note " & _
        "FROM StatusTable WHERE Machine = '" & fMachine & "' ORDER BY InsertTime DESC" & _
        ") S;"

fMachine是一个字符串,它包含我们当前正在寻找的机器。最终结果是 SQL 看起来像这样(对于机器 A10):

    SELECT M.msg_machine, M.msg_qtyorstatus, M.msg_entity, M.msg_operation, M.msg_creator, M.msg_insertdate,
        S.Machine, S.Status, S.InsertTime, S.Note, S.UserID
    FROM
        (SELECT TOP 1 msg_machine, msg_qtyorstatus, msg_entity, msg_operation, msg_creator
        FROM MARSTable WHERE msg_machine = '00A10' ORDER BY msg_insertdate DESC
        ) M,
        (SELECT TOP 1 Machine, Status, InsertTime, Note
        FROM StatusTable WHERE Machine = 'A10' ORDER BY InsertTime DESC
        ) S;

注意:我最初的示例使用了表的简化版本,但这个 SQL 是我生成的实际 SQL。 另外,我已经尝试过在每个字段/表格周围使用和不使用[方括号],它没有任何区别。

更新#2:我错过了第二个子查询中的一个字段。我添加了它,现在我得到了同样的错误,除了它说我缺少1参数,而不是2。现在 SQL 看起来像这样:

SELECT M.msg_machine, M.msg_qtyorstatus, M.msg_entity, M.msg_operation, M.msg_creator, M.msg_insertdate,
    S.Machine, S.Status, S.InsertTime, S.Note, S.UserID
FROM
    (SELECT TOP 1 msg_machine, msg_qtyorstatus, msg_entity, msg_operation, msg_creator
    FROM MARSTable WHERE msg_machine = '00A10' ORDER BY msg_insertdate DESC
    ) M,
    (SELECT TOP 1 Machine, Status, InsertTime, Note, UserID
    FROM StatusTable WHERE Machine = 'A10' ORDER BY InsertTime DESC
    ) S;

UserID是我在第二个子查询中缺少的字段。

已解决:我在第一个子查询中缺少另一个字段。一旦我澄清了这一点,解决方案就奏效了。SQL 现在看起来像这样:

SELECT M.msg_machine, M.msg_qtyorstatus, M.msg_entity, M.msg_operation, M.msg_creator, M.msg_insertdate,
    S.Machine, S.Status, S.InsertTime, S.Note, S.UserID
FROM
    (SELECT TOP 1 msg_machine, msg_qtyorstatus, msg_entity, msg_operation, msg_creator, msg_insertdate 
    FROM MARSTable WHERE msg_machine = '00A10' ORDER BY msg_insertdate DESC
    ) M,
    (SELECT TOP 1 Machine, Status, InsertTime, Note
    FROM StatusTable WHERE Machine = 'A10' ORDER BY InsertTime DESC
    ) S;

感谢所有在这里提供帮助的人。

4

2 回答 2

2

我怀疑 Access 是否完全外部连接。可能在最新版本中有所改进,但我不记得在 Access 中看到过这个。这是一个访问解决方案:

  1. 创建一个查询,返回任一表中的所有机器 ID:

    SELECT DISTINCT machine FROM marstable UNION SELECT DISTINCT machine FROM statustable

  2. 将该查询另存为,例如 QRY_MachinesAnywhere

  3. 创建第二个查询 LEFT JOIN 将此查询连接到两个表:

    从 QRY_MachinesAnywhere 任何地方选择任何地方 LEFT JOIN statustable ON anywhere.machine=statustable.machine LEFT JOIN marstable ON anywhere.machine=marstable.machine

(确切的语法可能略有不同 - Access 似乎喜欢 JOINed FROM 表达式中的括号,并且一次只连接两个东西 - 并且可能需要“QRY_MachinesAnywhere”和“anywhere”之间的显式 AS:但如果您添加 Qry_MachinesAnywhere 和原始使用 UI 设计器将表放入查询中,在机器上加入,你应该没问题)。

请注意,您需要进入 SQL 视图才能创建原始 UNION 查询。在设计器中无法做到这一点。

于 2012-11-16T15:50:48.280 回答
2

由于您只需要一行,因此您可以使用两个返回一行的子查询来完成,并且根本不需要加入它们

PARAMETERS param Text(50);
SELECT
    [param] AS machine,
    M.quantity, M.[order], M.operation, M.insertdate,
    S.status, S.inserttime, S.note
FROM
    ( SELECT TOP 1 machine, quantity, [order], operation, insertdate
      FROM marstable
      WHERE machine = [param]
      ORDER BY insertdate DESC
    ) M,
    ( SELECT TOP 1 machine, status, inserttime, note
      FROM statustable
      WHERE machine = [param]
      ORDER BY inserttime DESC
    ) S
于 2012-11-16T16:45:43.440 回答