Search code examples
sqlms-accessms-wordmailmerge

Access SQL query to mailmerge


How can I transform this table from this

id name
1  sam
2  nick
3  ali
4  farah
5  josef
6  fadi

to

id1   name1   id2   name2   id3   name3   id4  name4
1     sam     2     nick    3     ali      4   farah
5     josef   6     fadi

the reason i need this is i have a database and i need to do a mail merge using word and I want to print every 4 rows on one page, MS word can only print one row per page, so using an SQL query I want one row to represent 4 rows

thanks in advance

Ali


Solution

  • You don't need to create a query for this in Access. Word has a merge field called <<Next Record>> which forces moving to the next record. If you look at how label documents are created using the Mail Merge Wizard, you'll see that's how it's done.

    Updated - Doing this in SQL

    The columns in simple SELECT statements are derived from the columns from the underlying table/query (or from expressions). If you want to define columns based on the data, you need to use a crosstab query.

    First create a query with a running count for each person (say your table is called People), and calculate the row and column position from the running count:

    SELECT People.id, Count(*)-1 AS RunningCount, int(RunningCount/4) AS RowNumber, RunningCount Mod 4 AS ColumnNumber
    FROM People 
    LEFT JOIN People AS People_1 ON People.id >= People_1.id
    GROUP BY People.id;
    

    (You won't be able to view this in the Query Designer, because the JOIN isn't comparing with = but with >=.)

    This query returns the following results:

    id  Rank  RowNumber  ColumnNumber
    1   0     0          0
    2   1     0          1
    3   2     0          2
    4   3     0          3
    5   4     1          0
    6   5     1          1
    

    Assuming this query is saved as Positions, the following query will return the results:

    TRANSFORM First(Item) AS FirstOfItem
    SELECT RowNumber
    FROM (
        SELECT ID AS Item, RowNumber, "id" &( ColumnNumber + 1) AS ColumnHeading
        FROM Positions
    
        UNION ALL SELECT Name, RowNumber, "name" & (ColumnNumber +1)
        FROM Positions
        INNER JOIN People ON Positions.id = People.id
    ) AS AllValues
    GROUP BY AllValues.RowNumber
    PIVOT AllValues.ColumnHeading In ("id1","name1","id2","name2","id3","name3","id4","name4");
    

    The UNION is there so each record in the People table will have two columns - one with the id, and one with the name.

    The PIVOT clause forces the columns to the specified order, and not in alphabetical order (e.g. id1, id2 ... name1, name2...)