2011-03-02 57 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