在Access中执行此操作的最佳方法是什么?
Create table tmp
(
plant int,
material vchar(20),
workcenter int,
setuptime vchar(20)
)
insert into tmp values( 1, mat1, 2, 30)
insert into tmp values( 1, mat1, 3, 30)
insert into tmp values( 1, mat2, 3, 30)
insert into tmp values( 1, mat2, 4, 30)
insert into tmp values( 2, mat1, 4, 30)
insert into tmp values( 2, mat1, 5, 30)
结果需要看起来像。
Plant Material Workcenter1 Setuptime1 Workcenter2 Setuptime2
1 Mat1 2 30 3 30
1 Mat2 3 30 4 30
2 Mat1 4 30 5 30
我当时认为这可行,但必须有更好的方法。
SELECT t.Plant,
t.Material,
t.Workcenter as Workcenter1,
t.setuptime as SetupTime1
t2.Workcenter as Workcenter2,
t2.setuptime as SetupTime2
FROM tmp t
LEFT JOIN tmp t2
on t.plant = t2.plant
and t.material = t2.material
非常感谢。
答案 0 :(得分:1)
您是否尝试过Crosstab查询?
修改强>
(重新格式化你的问题后,我的格式更好)
你的解决方案几乎可以工作。但是你得到的将是双重条目(如下所示):
Plant Material Workcenter1 Setuptime1 Workcenter2 Setuptime2
1 Mat1 2 30 2 30
1 Mat1 2 30 3 30
1 Mat1 3 30 2 30
1 Mat1 3 30 3 30
1 Mat2 3 30 4 30
1 Mat2 3 30 3 30
1 Mat2 4 30 3 30
1 Mat2 4 30 4 30
2 Mat1 4 30 5 30
2 Mat1 4 30 4 30
2 Mat1 5 30 5 30
2 Mat1 5 30 4 30
如果你有两个以上的工作中心,那就更糟了。
所以你想要的是一个列指示器
Create table tmp
(
plant int,
material vchar(20),
workcenter int,
setuptime vchar(20),
myCol int
);
(顺便说一句,vchars将无法在ms-access / Jet中使用...但是字符将会出现)
insert into tmp values( 1, mat1, 2, 30, 1);
insert into tmp values( 1, mat1, 3, 30, 2);
insert into tmp values( 1, mat2, 2, 30, 1);
insert into tmp values( 1, mat2, 3, 30, 2);
insert into tmp values( 2, mat1, 4, 30, 1);
insert into tmp values( 2, mat1, 5, 30, 2);
SELECT tmp.plant, tmp.material, tmp.workcenter, tmp.setuptime,
tmp_1.workcenter, tmp_1.setuptime
FROM tmp INNER JOIN tmp AS tmp_1 ON (tmp.material = tmp_1.material)
AND (tmp.plant = tmp_1.plant)
WHERE (((tmp.myCol)=1)
AND ((tmp_1.myCol)=2));
当然,如果您可以编辑原始表,也许您只想添加第二个Workcenter和Setuptime列,
答案 1 :(得分:1)
您的样本输出不明确 - 我认为它看起来像:
Plant | Mat | Wkcntr1 | STime1 | Wkcntr2 | STime2
1 | Mat1 | 2 | 30 | 3 | 30
1 | Mat2 | 3 | 30 | 4 | 30
2 | Mat1 | 4 | 30 | 5 | 30
我会说桌子没有理想的设置。看起来它没有主键,因此不清楚哪一条记录属于1列,哪条记录属于2列。
我会为RecordNumber添加一个额外的字段(1或2),然后你有一个Plant,Material和RecordNumber的主键。
您的查询将如下所示:
SELECT tmp.plant, tmp.material, tmp.workcenter AS W1, tmp.setuptime AS S1, tmp_1.workcenter AS W2, tmp_1.setuptime AS S2
FROM tmp INNER JOIN tmp AS tmp_1 ON (tmp.material = tmp_1.material) AND (tmp.plant = tmp_1.plant)
WHERE (((tmp.recordNum)=1) AND ((tmp_1.recordNum)=2));
这只适用于有限(且已知)数量的数字(无论1和2代表什么)。
答案 2 :(得分:1)
根据我对您要解决的问题的理解,我认为使用标准SQL查询(至少不在Access中)是不可行的。
我试图破解一些符合你想要的代码(我认为)。
如何使用
只需将以下代码复制/粘贴到VBA模块中即可 从代码中,或者,如果要测试它,请从VBA IDE立即窗口中调用:
ExpandTable
<强>假设强>
temp
包含您要展开的数据,其中包含工厂/材料/工作/等temp
表不为空(我省略了一些代码检查以避免样本膨胀)。result
。<强>代码强>
Public Sub ExpandTable()
Dim db As DAO.Database
Dim rs As DAO.Recordset, rs2 As DAO.Recordset
Dim td As DAO.TableDef
Dim fd As DAO.Field
Dim maxWorkCenters As Integer
Dim i As Integer
Dim sql As String
Set db = CurrentDb
' Delete the old result table if there was one '
On Error Resume Next
db.TableDefs.Delete "result"
On Error GoTo 0
' Create the result table '
Set td = db.CreateTableDef("result")
td.Fields.Append td.CreateField("Plant", dbInteger)
td.Fields.Append td.CreateField("Material", dbText)
' Get the maximum number of workcenters we will need '
' for a given Plan/Material combination '
sql = "SELECT Count(*) FROM Temp GROUP BY Plant, Material"
Set rs = db.OpenRecordset(sql, dbOpenSnapshot)
maxWorkCenters = Nz(rs.Fields(0).Value, 0)
rs.Close
Set rs = Nothing
' Create as many columns as we need to fit all these combinations '
For i = 1 To maxWorkCenters
td.Fields.Append td.CreateField("WorkCenter" & i, dbText)
td.Fields.Append td.CreateField("SetupTime" & i, dbInteger)
Next i
db.TableDefs.Append td
' Now get the data into the new table '
Dim lastPlant As Variant, lastMaterial As Variant
Dim curcol As Integer
sql = "SELECT Plant, Material, Workcenter, Setuptime FROM Temp ORDER BY Plant, Material, WorkCenter"
Set rs = db.OpenRecordset(sql, dbOpenSnapshot)
Set rs2 = db.OpenRecordset("result", dbOpenDynaset)
With rs
lastPlant = 0
lastMaterial = ""
Do While Not .EOF
If (Nz(!Plant) <> lastPlant) Or (Nz(!Material) <> lastMaterial) Then
If rs2.EditMode = dbEditAdd Then
' Save the previously edited record if any '
rs2.Update
End If
' Different plant/material, so we add a new result '
rs2.AddNew
rs2!Plant = !Plant
rs2!Material = !Material
rs2!WorkCenter1 = !WorkCenter
rs2!SetupTime1 = !Setuptime
lastPlant = Nz(!Plant)
lastMaterial = Nz(!Material)
curcol = 1
Else
' Same plant/material combi, so we fill the next column set '
curcol = curcol + 1
rs2.Fields("Workcenter" & curcol).Value = !WorkCenter
rs2.Fields("SetupTime" & curcol).Value = !Setuptime
End If
.MoveNext
Loop
If rs2.EditMode = dbEditAdd Then
' Save the last result '
rs2.Update
End If
End With
Set rs2 = Nothing
Set rs = Nothing
Set db = Nothing
End Sub
关于代码
result
时都会重新创建ExpandTable
表。WorkCenterX
和SetupTimeX
列的数量会适应实际的唯一工厂/材料对的数量。测试数据库
您可以从http://blog.nkadesign.com/wp-content/uploads/SO/SO547777.zip下载测试Access 2000数据库。
无论如何,希望它做你想要的或至少让你更接近。
答案 3 :(得分:0)
我不太清楚访问语法给你一个完整的答案,但是为了帮助你自己的调查,我可以告诉你,你想要做的事情被称为“交叉表”查询或“数据透视”。 / p>
在谷歌中使用这些关键字可以帮助你。
答案 4 :(得分:0)
在查询向导中有一个交叉表选项,可以将表格水平放置。这不是你想要的吗?