4

工場の作業現場でマシンを追跡する Access データベースがあります。私が使用している2つのテーブルがあります:

  1. marstable- 各マシンが完了した操作のリスト
  2. statustable- マシンのステータス変更のリスト

marstableには約 100,000 のエントリがありますがstatustable、100 未満です。

次の 3 つのいずれかを見つけるには、一度に 1 台のマシンを検索する必要があります。

  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 スキルが不足していることをご容赦ください。

更新#1:

以下の彼の回答の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: 2 番目のサブクエリのフィールドがありませんでした。私はそれを追加しましたが、同じエラーが表示されますが、 2ではなく1つのパラメーター。これで、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;

UserID2 番目のサブクエリで欠落していたフィールドです。

解決済み:最初のサブクエリから別のフィールドが欠落していました。それを片付けたら、解決策はうまくいきました。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 が FULL OUTER JOINS を行うとは思えません。最新バージョンでは改善されている可能性がありますが、Access でこれを見た覚えがありません。アクセスソリューションは次のとおりです。

  1. いずれかのテーブルにあるすべてのマシン ID を返すクエリを作成します。

    SELECT DISTINCT machine FROM marstable UNION SELECT DISTINCT machine FROM statustable

  2. そのクエリを、たとえば QRY_MachinesAnywhere として保存します。

  3. このクエリを両方のテーブルに LEFT JOIN する 2 つ目のクエリを作成します。

    SELECT どこでも.machine[, その他のもの] FROM QRY_MachinesAnywhere どこでも LEFT JOIN statustable ON どこでも.machine=statustable.machine LEFT JOIN marstable ON どこでも.machine=marstable.machine

(正確な構文は若干異なる場合があります - Access は JOINed FROM 式のブラケットを好み、一度に 2 つのもののみを結合するようです - そして、"QRY_MachinesAnywhere" と "anywhere" の間に明示的な AS が必要になる場合があります: ただし、Qry_MachinesAnywhere と元の両方を追加すると、 UI デザイナーを使用してクエリにテーブルを追加し、マシン上で結合すれば問題ありません)。

元の UNION クエリを作成するには、SQL ビューに移動する必要があることに注意してください。デザイナでこれを行うことはできません。

于 2012-11-16T15:50:48.280 に答える
2

必要な行は 1 つだけなので、両方の行を返す 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 に答える