2011-03-02 33 views
12

我在MS Access 2007中有一个问题,我希望有人有答案。我有一张很长但很简单的表格,其中包含客户名称以及每周交付的日子。我想总结一下这张表,把名字和所有的日子列入一个新的字段“ALLDays”,同时保留所有的数据。Microsoft Access精简表中的多行

源表看起来是这样的:

Name   Day 
CustomerA Monday 
CustomerA Thursday 
CustomerB Tuesday 
CustomerB Friday 
CustomerC Wednesday 
CustomerC Saturday 

我想有一个查询返回这样的结果:

Name   ALLDays 
CustomerA Monday, Thursday 
CustomerB Tuesday, Friday 
CustomerC Wednesday, Saturday 

感谢。

+0

通常,您会使用交叉表查询。转到“创建”选项卡来创建查询,然后查询设计的设计视图。添加表格以查看内容。然后选择“设计”标签,“交叉表”。 – david 2013-09-11 09:33:44

+0

请参阅http://stackoverflow.com/questions/1920552/concatenate-rows-into-1-access-2007/1921002#1921002,特别参考有关ADODB记录集的注释。 – Fionnuala 2011-03-02 23:14:33

回答

19

通常你必须写一个函数,将允许您创建一个连续清单。这是我用过的:

Public Function GetList(SQL As String _ 
          , Optional ColumnDelimeter As String = ", " _ 
          , Optional RowDelimeter As String = vbCrLf) As String 
'PURPOSE: to return a combined string from the passed query 
'ARGS: 
' 1. SQL is a valid Select statement 
' 2. ColumnDelimiter is the character(s) that separate each column 
' 3. RowDelimiter is the character(s) that separate each row 
'RETURN VAL: Concatenated list 
'DESIGN NOTES: 
'EXAMPLE CALL: =GetList("Select Col1,Col2 From Table1 Where Table1.Key = " & OuterTable.Key) 

Const PROCNAME = "GetList" 
Const adClipString = 2 
Dim oConn As ADODB.Connection 
Dim oRS As ADODB.Recordset 
Dim sResult As String 

On Error GoTo ProcErr 

Set oConn = CurrentProject.Connection 
Set oRS = oConn.Execute(SQL) 

sResult = oRS.GetString(adClipString, -1, ColumnDelimeter, RowDelimeter) 

If Right(sResult, Len(RowDelimeter)) = RowDelimeter Then 
    sResult = Mid$(sResult, 1, Len(sResult) - Len(RowDelimeter)) 
End If 

GetList = sResult 
oRS.Close 
oConn.Close 

CleanUp: 
    Set oRS = Nothing 
    Set oConn = Nothing 

Exit Function 
ProcErr: 
    ' insert error handler 
    Resume CleanUp 

End Function 

Remou的版本具有附加功能,您可以传递值的数组而不是SQL语句。


样品查询可能看起来像:

SELECT SourceTable.Name 
    , GetList("Select Day From SourceTable As T1 Where T1.Name = """ & [SourceTable].[Name] & """","",", ") AS Expr1 
FROM SourceTable 
GROUP BY SourceTable.Name; 
+0

顺便说一句,我明显地剥离了我使用的PROCNAME常量的错误处理程序。 – Thomas 2011-03-02 23:30:33

+0

非常感谢您的帮助,但我在这方面相当新,并且您的答案略高于我的水平。你愿意给我具体吗?我的源表称为CustomerRoutes。这两个字段是名称和日期。所以我创建一个模块并写出确切的代码?以及我究竟如何调用GetList函数,我假设我在SQL模式下创建一个新的查询并写入类似于Select(“Name,Day from ...?Thanks。 – 2011-03-03 03:59:15

+0

@Sam_H - 首先,您需要将代码放入然后,您可以使用OP中提到的“SourceData”中的不同客户创建一个普通查询(因此,每个客户一行),您可能需要创建一个Group By查询,然后,其中的一列查询你将输入一个公式:'= GetList(“Select Day From SourceData As S1 Where S1.Day =”&SourceData.Col)'。这样,你在主查询中使用一列来构建一个Select查询GetList函数。 – Thomas 2011-03-03 05:38:46

1

这里有一个简单的解决方案,不需要VBA。它使用更新查询将值连接到字段上。

我会用我使用的例子证明这一点。

我有一个表“emails_by_team”有两个字段“TEAM_ID”和“email_formatted”。我想要的是以一个字符串收集给定团队的所有电子邮件。

1)I创建表 “team_more_info” 具有两个字段: “TEAM_ID” 和 “team_emails”

2)填充 “team_more_info” 与 “emails_by_team”

3)所有的 “TEAM_ID”新建一个用于更新查询 “emails_by_team” 为NULL
查询名称:team_email_collection_clear

UPDATE team_more_info 
SET team_more_info.team_emails = Null; 

4)这是这里的伎俩:创建更新查询
查询名称:team_email_collection_update

UPDATE team_more_info INNER JOIN emails_by_team 
    ON team_more_info.team_id = emails_by_team.team_id 
SET team_more_info.team_emails = 
    IIf(IsNull([team_emails]),[email_formatted],[team_emails] & "; " & [email_formatted]); 

5),以保持信息跟上时代的创建运行两个查询,当需要

首先宏:team_email_collection_clear

二: team_email_collection_update

QED

1

由于这只是一个小另一种没有VBA的方法是建立一系列IIF声明并连接结果。

SELECT name, 
    IIF(SUM(IIF(day = "Monday",1,0)) >0, "Monday, ") & 
    IIF(SUM(IIF(day = "Tuesday",1,0)) >0, "Tuesday, ") & 
    IIF(SUM(IIF(day = "Wednesday",1,0)) >0, "Wednesday, ") & 
    IIF(SUM(IIF(day = "Thursday",1,0)) >0, "Thursday, ") & 
    IIF(SUM(IIF(day = "Friday",1,0)) >0, "Friday, ") & 
    IIF(SUM(IIF(day = "Saturday",1,0)) >0, "Saturday, ") & 
    IIF(SUM(IIF(day = "Sunday",1,0)) >0, "Sunday, ") AS AllDays 
FROM Table1 
GROUP BY name 

如果你一个完美主义者,你甚至可以摆脱最后一个逗号的这样

SELECT name, 
LEFT(
    IIF(SUM(IIF(day = "Monday",1,0)) >0, "Monday, ") & 
    IIF(SUM(IIF(day = "Tuesday",1,0)) >0, "Tuesday, ") & 
    IIF(SUM(IIF(day = "Wednesday",1,0)) >0, "Wednesday, ") & 
    IIF(SUM(IIF(day = "Thursday",1,0)) >0, "Thursday, ") & 
    IIF(SUM(IIF(day = "Friday",1,0)) >0, "Friday, ") & 
    IIF(SUM(IIF(day = "Saturday",1,0)) >0, "Saturday, ") & 
    IIF(SUM(IIF(day = "Sunday",1,0)) >0, "Sunday, "), 
LEN(
    IIF(SUM(IIF(day = "Monday",1,0)) >0, "Monday, ") & 
    IIF(SUM(IIF(day = "Tuesday",1,0)) >0, "Tuesday, ") & 
    IIF(SUM(IIF(day = "Wednesday",1,0)) >0, "Wednesday, ") & 
    IIF(SUM(IIF(day = "Thursday",1,0)) >0, "Thursday, ") & 
    IIF(SUM(IIF(day = "Friday",1,0)) >0, "Friday, ") & 
    IIF(SUM(IIF(day = "Saturday",1,0)) >0, "Saturday, ") & 
    IIF(SUM(IIF(day = "Sunday",1,0)) >0, "Sunday, ") 
) - 2 
) 
AS AllDays 
FROM Table1 
GROUP BY name 

您也可以考虑让他们在单独的列,因为如果访问该查询,这可能证明更有效从另一个。例如,仅查找星期二的实例会更容易。例如:

SELECT name, 
IIF(SUM(IIF(day = "Monday",1,0)) >0, "Monday") AS Monday, 
IIF(SUM(IIF(day = "Tuesday",1,0)) >0, "Tuesday") AS Tuesday, 
IIF(SUM(IIF(day = "Wednesday",1,0)) >0, "Wednesday") AS Wednesday, 
IIF(SUM(IIF(day = "Thursday",1,0)) >0, "Thursday") AS Thursday, 
IIF(SUM(IIF(day = "Friday",1,0)) >0, "Friday") AS Friday, 
IIF(SUM(IIF(day = "Saturday",1,0)) >0, "Saturday") AS Saturday, 
IIF(SUM(IIF(day = "Sunday",1,0)) >0, "Sunday") AS Sunday 
FROM Table1 
GROUP BY name