我有一个包含许多列的表,但感兴趣的是两个:订单号和产品类型。目前,该表每个订单有多个产品类型。如果客户订购了电话服务,电视服务和互联网服务,则会有三条记录 - 每条服务一条记录,但都具有相同的订单号。我想创建一个引用表来存储一个连接的字符串,其中包含客户订购的所有服务。这样我就可以使用这种更合理的方法来汇总我的数据。我正在使用标准的Access 2010数据库。
**Current table:**
Order Number | Product Types
100001 | TV
100001 | Phone
100001 | Internet
100002 | Phone
100003 | TV
100003 | Internet
所需参考表
100001 | TV/Phone/Internet
100002 | Phone
100003 | TV/Internet
答案 0 :(得分:4)
Allen Browne提供了一个对此有用的功能:Concatenate values from related records。将该函数的代码保存在标准模块中。
SELECT DISTINCT
[Order Number],
ConcatRelated("[Product Types]",
"YourTable",
"[Order Number] = " & [Order Number],
"[Product Types]",
"/"
) AS All_Product_Types
FROM YourTable;
我在Access 2007中测试了该查询,并将示例数据保存在名为“ YourTable ”的表中。它返回了您要求的结果。但是,这仅适用于Access会话。如果您想从Access外部运行此查询(例如从ASP),则用户定义的函数不可用,因此您将收到有关ConcatRelated()
无法识别的错误。
因此,您可以使用查询在需要时检索连接值。但是,如果存储这些连接值,它们很快就会与基表数据的更改不同步。
答案 1 :(得分:0)
您不应创建连接记录的引用表。那就是对数据库进行非规范化。
您可以尝试下面的交叉表查询,但我还没有测试过。您可以read here获取更多信息。
TRANSFORM First([Product Types]) AS Product
SELECT [Order Number], First([Product Types])
FROM CurrentTable
GROUP [Order Number]
答案 2 :(得分:0)
如果我理解了这个问题,你就会问如何获得那些拥有电视,手机和互联网的订单的订单号。如果您只对这些订单号感兴趣,可以运行如下查询:
SELECT Distinct Table1.OrderNumber
FROM (Select OrderNumber from Table1 where [product types]= "Internet") AS i
INNER JOIN ((Select OrderNumber from Table1 where [product types]="Phone") AS p
INNER JOIN ((Select OrderNumber from Table1 Where [product types]= "TV") AS tv
INNER JOIN Table1 ON tv.OrderNumber = Table1.OrderNumber) ON p.OrderNumber = Table1.OrderNumber) ON i.OrderNumber = Table1.OrderNumber;
答案 3 :(得分:0)
正如oneday在SO早期的帖子中指出的那样,ADO更容易: 示例查询:
SELECT [Order Number],
ConcatADO("SELECT [Product Types] FROM Orders
WHERE [Order Number]=" & [Order Number],", "," : ") AS Cat
FROM Orders
GROUP BY [Order Number], 2;
使用ADO的功能
Function ConcatADO(strSQL As String, strColDelim, _
strRowDelim, ParamArray NameList() As Variant)
Dim rs As New ADODB.Recordset
Dim strList As String
On Error GoTo Proc_Err
If strSQL <> "" Then
rs.Open strSQL, CurrentProject.Connection
strList = rs.GetString(, , strColDelim, strRowDelim)
strList = Mid(strList, 1, Len(strList) - Len(strRowDelim))
Else
strList = Join(NameList, strColDelim)
End If
ConcatADO = strList
Exit Function
Proc_Err:
ConcatADO = "***" & UCase(Err.Description)
End Function