今日を持っているので、私は、私はこのカスタムソリューションを作成したい考え出し。これらのステップのすべての回答は他の場所にありますが、すべての考案されたソリューションを分類するのは簡単ではありませんでした。
行を列に変更する基本的な答えはhereです。しかし、この質問のデータとは異なり、その回答のサンプルデータはすでに適切に順序付けられていました。列値[ID]と[電子メール]が一意のペアを形成し、NULL値を持たない限り、集約サブクエリまたはAccess集計関数の呼び出しを使用して適切な順序を生成することが可能です。クエリの全体数を減らすために、私は先に進み、同じクエリで変換された列名を生成しました。値が一意でないか、またはヌル値を持つ場合、シーケンシングはオフになり、最終結果にはデータが欠落します。 Access SQL Transformステートメント(クロス集計クエリ)では、クエリごとに1つの変換列しか使用できません。 2つの別々のクエリを作成して結合するのは簡単ですが、クロス集計クエリでは動的な(つまり未定義の)数の列が生成されるため、各列を順番に選択することなく電子メールとコメントの列をインターリーブすることはできません。さらに、問合せにどの列が含まれているかを明示的に指定すると、クロス集計問合せの動的な側面が破壊され、追加の列が残されるか、全体の列数が減るとエラーが発生します。
UPDATE:ちょうど(今ソリューション2ラベル)元の溶液を掲示した後、私は実際に後方に一歩を行くことによって、列インターリーブ問題を解決することができることを実現... は最初以上の行 --one列を生成します最終的な変換の前に、それらを同じ行にまとめて配置します。
ソリューション1
次のクエリを保存し、[シーケンス・]という名前を付けます。[後方]
SELECT Data.ID, Data.Email, Data.Comments,
1 + DCount("[ID]","Data","[ID]=" & [ID] & " and [Email]<'" & Replace([Email],"'","''") & "'") AS SeqNum,
Format([SeqNum],"000") & ' Email' AS EmailColumn,
Format([SeqNum],"000") & ' Remark' AS CommentsColumn
FROM Data
ORDER BY Data.ID, Data.Email;
保存し、次のクエリと名前それ::それは[メール]の後にソートしますので、最終的な出力で正しい列の順序を容易にするために、私は言葉の代わりに「コメント」の「備考」を使用
SELECT ID, EmailColumn AS ColumnName, Email AS [Value]
FROM Sequenced
UNION SELECT ID, CommentsColumn AS ColumnName, Comments AS [Value]
FROM Sequenced
ORDER BY [ID], [ColumnName];
保存し、次のクエリと[InterleavedCrosstab]という名前を付けます:
TRANSFORM First(Backwards.Value) AS FirstOfValue
SELECT Backwards.ID
FROM Backwards
GROUP BY Backwards.ID
ORDER BY Backwards.ID, Backwards.ColumnName
PIVOT Backwards.ColumnName;
ソリューション2
保存し、次のクエリと名前を付け、[Sequenced2]:
SELECT Data.ID, Data.Email, Data.Comments,
1 + DCount("[ID]","Data","[ID]=" & [ID] & " and [Email]<'" & Replace([Email],"'","''") & "'") AS SeqNum,
'Email' & Format([SeqNum],"000") AS EmailColumn,
'Comments' & Format([SeqNum],"000") AS CommentsColumn
FROM Data
ORDER BY Data.ID, Data.Email;
保存し、次のクエリと名前を付け、[EmailCrosstab]:
TRANSFORM First(Sequenced2.Email) AS FirstOfEmail
SELECT Sequenced2.ID
FROM Sequenced2
GROUP BY Sequenced2.ID
ORDER BY Sequenced2.ID
PIVOT Sequenced2.EmailColumn;
保存し、次のクエリと名前を[CommentsCrosstab] :
TRANSFORM First(Sequenced2.Comments) AS FirstOfComments
SELECT Sequenced2.ID
FROM Sequenced2
GROUP BY Sequenced2.ID
ORDER BY Sequenced2.ID
PIVOT Sequenced2.CommentsColumn;
最後に、最も一般的な結果のクエリはすべての列を返しますが、それらはインターリーブされません。 [ID]列が重複します:
SELECT EmailCrosstab.*,
CommentsCrosstab.*
FROM CommentsCrosstab INNER JOIN EmailCrosstab
ON CommentsCrosstab.ID = EmailCrosstab.ID;
ここで清書版だが、わずか3電子メールやコメントの列まであります。私が持っていた
SELECT EmailCrosstab.ID,
EmailCrosstab.Email001,CommentsCrosstab.Comments001,
EmailCrosstab.Email002,CommentsCrosstab.Comments002,
EmailCrosstab.Email003,CommentsCrosstab.Comments003
FROM CommentsCrosstab INNER JOIN EmailCrosstab
ON CommentsCrosstab.ID = EmailCrosstab.ID;
ソリューション3
は、クエリのみのソリューションがかなり簡単であることを認識したときに、既に以下のVBAプロシージャを入力しています。
Public Sub CustomTransform()
'* This code assumes that the field values
'* [ID] and [Email] constitute a unique pair
'* and that there are NO NULL values.
Dim i As Integer, MaxIDRows As Integer
Dim IDSeq As Integer
Dim lastID As Long
Dim IDstring As String
Dim tbl As TableDef
Dim idx As Index
Dim db As Database
Dim rsSrc As Recordset2, rsResult As Recordset2
Const resultTable As String = "Customer Crosstab"
Set db = CurrentDb
MaxIDRows = db.OpenRecordset(_
"SELECT Max(Counter.Rows) AS MaxRows" & _
" FROM (SELECT Count(Data.[ID]) AS [Rows]" & _
" FROM Data GROUP BY Data.[ID]) AS Counter" _
).Fields(0).Value
'* Column count <= 254 : ID + N * (Email + Comment columns)
If MaxIDRows = 0 Then
MsgBox "No data.", vbOKOnly Or vbExclamation, "No Data"
Exit Sub
ElseIf MaxIDRows >= 252/2 Then
MsgBox "Maximum number of columns exceeded.", _
vbOKOnly Or vbExclamation, "Maximum Columns Exceeded"
Exit Sub
End If
On Error Resume Next
db.TableDefs.Delete resultTable
Err.Clear
On Error GoTo 0
Set tbl = db.CreateTableDef(resultTable)
With tbl
' Create fields and append them to the new TableDef
' object. This must be done before appending the
' TableDef object to the TableDefs collection of the
' Northwind database.
.Fields.Append .CreateField("ID", dbLong)
For i = 1 To MaxIDRows
IDstring = Format(i, "000")
.Fields.Append .CreateField("Email" & IDstring, dbText, 255)
.Fields.Append .CreateField("Comments" & IDstring, dbText, 255)
Next
Set idx = .CreateIndex("Primary Key")
idx.Fields.Append idx.CreateField("ID")
idx.Primary = True
.Indexes.Append idx
End With
db.TableDefs.Append tbl
Set rsResult = db.OpenRecordset(resultTable, dbOpenTable)
Set rsSrc = db.OpenRecordset(_
"SELECT ID, Email, Comments" & _
" FROM Data" & _
" ORDER BY ID, Email")
lastID = -1
Do Until rsSrc.EOF
If rsSrc!id <> lastID Then
If lastID <> -1 Then
rsResult.Update
End If
IDSeq = 0
rsResult.AddNew
rsResult!id = rsSrc!id
End If
lastID = rsSrc!id
IDSeq = IDSeq + 1
IDstring = Format(IDSeq, "000")
rsResult.Fields("Email" & IDstring) = rsSrc!email
rsResult.Fields("Comments" & IDstring) = rsSrc!Comments
rsSrc.MoveNext
Loop
rsSrc.Close
If rsResult.EditMode <> dbEditNone Then
rsResult.Update
End If
rsResult.Close
Debug.Print "CustomTransform Done"
End Sub
あなたのデータにはNがありますか?アクセスには255列の本来の制限があります。 –
元のデータには他の固有のキーがありますか? IDは一意ではないが、電子メールアドレスとコメントのソースには別の固有のキーがあるのだろうか? –
Nothing/255に達してはいけません。私の現在のソースを調べると最高のものは155です。私はデータを使って新しいテーブルを作成し、新しい行を作成するために新しい自動生成キーを追加できます。これは役に立ちますか? –