1

こんにちは、マシンに関する情報を保持する (詳細) というテーブルがあります (各マシンには 1 つのレコードしかありません)。

MachineId    PersonId
---------------------
MacA         PersY
MacB         PersX

メンテナンスのための呼び出しを保持する別のテーブル (呼び出し) があります。

CallId        MachineId
-----------------------
Call01       MacA
Call02       MacB
Call03       MacA

そして、通話に応答した人を保持する 3 番目のテーブル (Visit):

CallId        PersonId       Date
--------------------------------
Call01       PersA          15/05/2013
Call02       PersB          20/05/2013
Call03       PersC          25/08/2013

必要なのは、電話に最後に応答した人で Details テーブルを更新するクエリを 1 つ作成することです。この例では、MacA は PersC で、MacB は PersB です。

私の問題は、Access 2003 で実行する必要があることです。SELECT TOP 1 PersonId ORDER BY Date DESC を使用してサブクエリを実行し、テーブル間の関係を作成しようとしました (SQL サーバーでは機能しますが、ここでは機能しません)。

ありがとう。試しました:

UPDATE Details SET Details.PersonId = t.Person 
FROM Details INNER JOIN
(SELECT TOP 1 Call.MachineId, Visit.PersonId AS Person 
 FROM Call INNER JOIN Visit ON Call.CallId = Visit.CallId 
 ORDER BY Visit.Date DESC) AS t ON Details.MachineId = t.MachineId;
4

2 に答える 2

2

SELECT相関サブクエリを含むクエリを使用して、適切なPersonIdfor eachを取得できますMachineId

SELECT
    d.MachineId,
    (
        SELECT TOP 1 v.PersonId
        FROM
            Visit AS v
            INNER JOIN Calls AS c
            ON v.CallId = c.CallId
        WHERE c.MachineId = d.MachineId
        ORDER BY v.Date DESC
    ) AS person_id
FROM Details AS d;

このアプローチの利点は、非常に単純であり、Visitおよび/またはCallsテーブルのデータが変更されるたびに結果が常に一貫することです。UPDATEつまり、最新の結果を表示するために an を実行する必要はありません。

に格納されている値を変更する必要がある場合Details.PersonId、相関サブクエリを直接使用するだけでは不十分です。

于 2013-09-02T13:37:20.820 に答える
1

MS Access Jet/ACE db エンジンは、サブクエリを介した UPDATE をサポートしていません (他の制限の中でも特に)。

次の 3 つの主要なオプションがあります。

オプション 1: 一時テーブル

最初に「テーブルの作成」クエリとしてサブクエリを実行します。

SELECT Call.MachineId, Visit.PersonId AS Person INTO temp_T 
FROM Call INNER JOIN Visit ON Call.CallId = Visit.CallId 
ORDER BY Visit.Date DESC

次に、結果の一時テーブルを使用して更新を行います。

UPDATE Details SET Details.PersonId = t.Person 
FROM Details INNER JOIN temp_T AS t ON Details.MachineId = t.MachineId

オプション 2: クエリとドメイン集計関数を選択する

選択クエリを作成して保存し、UPDATE クエリで値を設定するときに DLookup を使用します。ストック DLookup 関数では並べ替え順序を指定できないため、選択クエリを保存する必要があります。

SELECT Call.MachineId, Visit.PersonId 
FROM Call INNER JOIN Visit ON Call.CallId = Visit.CallId 
ORDER BY Visit.Date DESC

上記を LastCalledTech という名前のクエリに保存します。次に、UPDATE クエリを次のように変更します。

UPDATE Details SET Details.PersonId = 
    DLookup("PersonID", "LastCalledTech", "MachineID=" & Details.MachineID)

オプション 3: 変更された DLookup() カスタム関数

Allen Browne は、ソート順を指定できる「拡張」DLookup 関数を作成しました。さらに関数を少し変更して、(テーブルやクエリ名だけでなく) 任意の SELECT ステートメントを渡すことができるようにしました。この場合、sort パラメータは実際には必要ありません。単純に SELECT SQL 文字列に含める方が効率的だからです。この関数 (以下に投稿しました) を使用して、次の UPDATE クエリを実行します。

UPDATE Details SET Details.PersonId = 
    ELookup("PersonID", "SELECT Call.MachineId, Visit.PersonId 
                         FROM Call INNER JOIN Visit ON 
                              Call.CallId = Visit.CallId
                         ORDER BY Visit.Date DESC", 
            "MachineID=" & Details.MachineID)

そして、ここに変更された関数があります:

Public Function ELookup(Expr As String, Domain As String, Optional Criteria As Variant, _
    Optional OrderClause As Variant) As Variant
On Error GoTo Err_ELookup
    'Purpose:   Faster and more flexible replacement for DLookup()
    'Arguments: Same as DLookup, with additional Order By option.
    'Return:    Value of the Expr if found, else Null.
    '           Delimited list for multi-value field.
    'Author:    Allen Browne. allen@allenbrowne.com
    'Updated:   December 2006, to handle multi-value fields (Access 2007 and later.)
    '           {by mwolfe02} Add parentheses to allow passing arbitrary SELECT statements
    'Examples:
    '           1. To find the last value, include DESC in the OrderClause, e.g.:
    '               ELookup("[Surname] & [FirstName]", "tblClient", , "ClientID DESC")
    '           2. To find the lowest non-null value of a field, use the Criteria, e.g.:
    '               ELookup("ClientID", "tblClient", "Surname Is Not Null" , "Surname")
    'Note:      Requires a reference to the DAO library.
    Dim db As DAO.Database          'This database.
    Dim rs As DAO.Recordset         'To retrieve the value to find.
    Dim rsMVF As DAO.Recordset      'Child recordset to use for multi-value fields.
    Dim varResult As Variant        'Return value for function.
    Dim strSql As String            'SQL statement.
    Dim strOut As String            'Output string to build up (multi-value field.)
    Dim lngLen As Long              'Length of string.
    Const strcSep = ","             'Separator between items in multi-value list.

    'Initialize to null.
    varResult = Null

    'Build the SQL string.
    strSql = "SELECT TOP 1 " & Expr & " FROM (" & Domain & ")"
    If Not IsMissing(Criteria) Then
        strSql = strSql & " WHERE " & Criteria
    End If
    If Not IsMissing(OrderClause) Then
        strSql = strSql & " ORDER BY " & OrderClause
    End If
    strSql = strSql & ";"

    'Lookup the value.
    Set db = DBEngine(0)(0)
    Set rs = db.OpenRecordset(strSql, dbOpenForwardOnly)
    If rs.RecordCount > 0 Then
        'Will be an object if multi-value field.
        If VarType(rs(0)) = vbObject Then
            Set rsMVF = rs(0).Value
            Do While Not rsMVF.EOF
                If rs(0).Type = 101 Then        'dbAttachment
                    strOut = strOut & rsMVF!FileName & strcSep
                Else
                    strOut = strOut & rsMVF![Value].Value & strcSep
                End If
                rsMVF.MoveNext
            Loop
            'Remove trailing separator.
            lngLen = Len(strOut) - Len(strcSep)
            If lngLen > 0& Then
                varResult = Left(strOut, lngLen)
            End If
            Set rsMVF = Nothing
        Else
            'Not a multi-value field: just return the value.
            varResult = rs(0)
        End If
    End If
    rs.Close

    'Assign the return value.
    ELookup = varResult

Exit_ELookup:
    Set rs = Nothing
    Set db = Nothing
    Exit Function

Err_ELookup:
    MsgBox Err.Description, vbExclamation, "ELookup Error " & Err.number
    Resume Exit_ELookup
End Function
于 2013-09-02T13:49:20.373 に答える