我遇到了一个问题,我们有3个表。 如果供应仓库没有该项目(删除),或者没有设置,它应该显示,但是根据源矩阵它应该是供应仓库。MS Access SQL连接问题在“重复”查询的情况下
简化布局应该看起来像这样。
表MainData
- 领域ITEMNO - 个人标识符,没有重复(PK)
- 领域的ItemType - 有一定的选择,我必须过滤一些 特定值。
表WarehouseData
- 领域ITEMNO - 与MainData有关,但PK与下一个场组合
- 领域ItemLocation - 给出具有货号描述的这样的物品的一个特定位置
- 字段商品分类 - 需要加入SourceWHMatrix
- 场ItemDeleted - 这是一个char场(因为出口数据),如果该项目被 “删除” 的值是 'X',否则空
表SourceWHMatrix(不是空的!)
- 领域ItemLocation - 前两个字段是主键
- 领域ItemCategory
- 场SourceLocation - 它应该给地方的项目将交付
我需要检查以下内容: 如果货号属于某些ItemType的(MainData表)和ItemDeleted是空然后是否这商品编号是在来源地(这是由确定来源WHMa trix基于商品位置AND商品分类)。必须列出的所有货号这是“被删除”在SourceLocation(在这种情况下,表WarehouseData场ItemLocation被检查返回SourceLocation值)OR甚至没有setupped这样的位置。
注:在同一情况下货号针对不同ItemLocation,ItemCategory并不总是一致的。并且每个ItemLocation有许多不同的ItemCategory来确定源仓库。
我尝试了很多LEFT JOIN组合,但似乎我无法列出那些没有设置的值。 (通过创建一个WarehouseData的重复表格,我可以在提供仓库时列出已删除的项目。)另外,我可以在VBA中用ADODB做到这一点,但是我想将所有内容保留在SQL代码中,甚至不使用自定义函数。它在Access 2010中,在其JET SQL引擎上运行。
这是行不通当前查询
SELECT MD.itemno,
MD.itemtype,
WD.itemlocation,
SMat.sourcelocation, --this could be empty
WD.itemdeleted AS "SourceWHDelFlag"
FROM maindata AS MD
INNER JOIN (warehousedata AS WD
INNER JOIN (sourcewhmatrix AS SMat
LEFT JOIN wd
ON SMat.sourcelocation = WD.itemlocation)
ON (WD.itemlocation = SMat.itemlocation
AND WD.itemcategory = SMat.itemcategory))
ON MD.itemno = WD.itemno
WHERE (MD.itemtype = 'Value1'
OR MD.itemtype = 'Value2')
这是我可以经过进一步的思考上来。然而,现在在我的i5上运行20分钟的查询。所以这不是最优的,而且当我可以检查Access的一些预结果时,似乎是将别名的语句添加到造成错误的where子句中,因为不再在同一个where子句中的其他字段上正确地过滤。所以这是我的“解决方案”:
SELECT MD.ItemNo,
MD.ItemType
WD.itemlocation,
SMat.sourcelocation, --this could be empty
(SELECT WD.ItemDeleted FROM WD WHERE WD.ItemNo = MD.ItemNo) AS "SourceWHDelFlag"
FROM MainData AS MD INNER JOIN (WarehouseData AS WD
LEFT JOIN SourceWHMatrix AS SMat
ON (WD.ItemLocation = SMat.ItemLocation
AND WD.ItemCategory = SMat.ItemCategory))
ON MD.ItemNo = WD.ItemNo
WHERE (MD.ItemType = 'Value1' OR MD.ItemType = 'Value2')
AND WD.ItemDeleted Is Null
AND WD.ItemCategory Is Not Null
AND WD.ItemCategory Not Like '##' -- This is another filter value, and it seems to be buggy
-- with SELECT clause in WHERE statement
AND (SELECT WD.ItemDeleted FROM WD WHERE WD.ItemNo = MD.ItemNo) Is Not Null
感谢您的帮助提前!
UPDATE 我做了一些VBA,这段代码实际上工作。我在代码中评论了所有必要的信息,但它仍然很慢。 (如果你有一个想法让它在合理的时间内运行得更快,我可以为它开放。)200条记录花费了大约10分钟,因此在16-17万条记录上运行需要15个小时。我可以在Excel中一些VLOOKUP做到这一点在Excel快得多......
Private Sub Command0_Click()
'initialize variables
Dim connDB As ADODB.Connection
Dim filtRecSet As ADODB.Recordset
Dim tmpRecSet As ADODB.Recordset
Dim tmpLineText As String
Dim tmpCounter As Integer
Dim filePath As String
Dim tmpFSO As New FileSystemObject
Dim tmpStream As TextStream
Dim startTime, endTime As Double
'set values
Set connDB = New ADODB.Connection
Set connDB = CurrentProject.Connection
Set filtRecSet = New ADODB.Recordset
Set tmpRecSet = New ADODB.Recordset
filePath = "C:\data\output.txt"
Set tmpStream = tmpFSO.CreateTextFile(filePath, True)
startTime = Now()
'this is a test database
'I previously deleted all not required MD.ItemType to test speed of SQL queries
'it's the reason for no filtering on MD.ItemType
'open base recordset, which are not deleted (WD.ItemDeleted)
'and belong tospecific MD.ItemType values
'and can match certain filters on WD.ItemCategory
With filtRecSet
.ActiveConnection = connDB
.Source = "SELECT MD.ItemNo, WD.ItemLocation, MD.ItemType, WD.ItemCategory, SMat.SourceLocation FROM MainData As MD INNER JOIN (WarehouseData As WD LEFT JOIN SourcwWHMatrix As SMat ON (WD.ItemLocation = SMat.ItemLocation AND WD.ItemCategory = SMat.ItemCategory)) ON MD.ItemNo = WD.ItemNo WHERE WD.ItemCategory Is Not Null AND WD.ItemCategory Not Like '[0-9][0-9]' AND WD.ItemDeleted Is Null"
.LockType = adLockOptimistic
.CursorType = adUseClient
End With
'RecordCount: 16610
'open control recordset for all appropiate MD.ItemType
With tmpRecSet
.ActiveConnection = connDB
.Source = "SELECT MD.ItemNo, WD.ItemLocation, MD.ItemType, WD.ItemCategory, SMat.SourceLocation FROM MainData As MD INNER JOIN (WarehouseData As WD LEFT JOIN SourcwWHMatrix As SMat ON (WD.ItemLocation = SMat.ItemLocation AND WD.ItemCategory = SMat.ItemCategory)) ON MD.ItemNo = WD.ItemNo"
.LockType = adLockOptimistic
.CursorType = adUseClient
.Filter = adFilterNone
End With
'RecordCount: 138713
filtRecSet.Open
'tmp variable to see how many records have been processed
tmpCounter = 1
If Not filtRecSet.EOF Then
'select first record
filtRecSet.MoveFirst
Do While Not filtRecSet.EOF
'find SourceLocation
tmpRecSet.Filter = "MATNR = '" & filtRecSet(0).Value & "' AND WERKS = '" & filtRecSet(5).Value & "'"
tmpRecSet.Open
'check how many records in recordset; there should not be more than one, that's why it considered as error
If tmpRecSet.RecordCount = 1 Then
tmpRecSet.MoveFirst
tmpLineText = filtRecSet(0).Value & "|" & filtRecSet(1).Value & "|" & filtRecSet(2).Value & "|" & filtRecSet(3).Value & "|" & filtRecSet(4).Value & "|" & filtRecSet(5).Value & "|" & tmpRecSet(3).Value
ElseIf tmpRecSet.RecordCount > 1 Then
tmpLineText = "ERROR"
'in case EOF is True -> no records
Else
tmpLineText = filtRecSet(0).Value & "|" & filtRecSet(1).Value & "|" & filtRecSet(2).Value & "|" & filtRecSet(3).Value & "|" & filtRecSet(4).Value & "|" & filtRecSet(5).Value & "|"
End If
Debug.Print "Record no.: " & tmpCounter
'write out text file
tmpStream.WriteLine tmpLineText
filtRecSet.MoveNext
tmpRecSet.Close
tmpCounter = tmpCounter + 1
Loop
End If
tmpStream.Close
endTime = Now()
Debug.Print "Elapsed time: " & CStr((endTime - startTime) * 24 * 60 * 60) & " seconds."
End Sub
它可能是你的一些有条件的地方,应放在LEFT JOIN。令人遗憾的是,您的要求的文字描述太难以解析。例如,那么是否很难遵循。也许你可以编辑你的问题,使它更简洁一些。例如一个项目符号列表。 – 2013-03-19 17:17:23
感谢您的回复康莱德。 – szucsitg 2013-03-19 17:26:48
它应该看起来像这样,希望我没有搞砸任何事情: SELECT MD.ItemNo,MD.ItemType,WD.ItemLocation,SMat.SourceLocation - >这可能是空的,WD.ItemDeleted AS“SourceWHDelFlag” - >这应该来自WD表检查时SourceLocation = ItemLocation FROM MainData AS MD INNER JOIN(WarehouseData AS WD INNER JOIN(SourceWHMatrix AS SMat LEFT JOIN WD ON SMat.SourceLocation = WD.ItemLocation)ON(WD.ItemLocation = SMat .ItemLocation AND WD.ItemCategory = SMat.ItemCategory)ON MD.ItemNo = WD.ItemNo。 – szucsitg 2013-03-19 17:41:22