Мне нужно транспонировать строки в столбцы в базе данных MS Access, VBA, SQL, и оба кода приветствуются.
Таблица
| Name | Ticker | ID | Innovation | Quality | Year |
| XYZ | PQR | 11 | 1 | 1 | 2009 |
| XYZ | PQR | 11 | 0 | 1 | 2010 |
| XYZ | PQR | 11 | 1 | 0 | 2011 |
| XYZ | PQR | 11 | 1 | 1 | 2012 |
Желаемая таблица
| Year | 2009 | 2010 | 2011 | 2012 |
| Name | XYZ | XYZ | XYZ | XYZ |
| Ticker | PQR | PQR | PQR | PQR |
| ID | 11 | 11 | 11 | 11 |
| Innovation | 1 | 0 | 1 | 1 |
| Quality | 1 | 1 | 0 | 1 |
Как вы можете видеть из нужного стола, я пытаюсь, чтобы строка Year как столбец и список всех столбцов, кроме Year, как мои строки. Я попытался использовать функцию Tranform и Pivot в MS Access, но она только сводит одну переменную. Дайте мне знать ваши мысли об этом.
Приведенный ниже код не удалось преобразовать все переменные.
TRANSFORM Max([Quality])
SELECT Ticker
FROM Table
Where Ticker = "XYZ"
GROUP BY Ticker
PIVOT Year;
Также, если возможно, я хочу опубликовать его как документ PDF.
Заранее спасибо, RVG
Это скрипт vb, который берет данные из TableSource и переносит их в TableTranspose. Вторая таблица должна быть настроена с столбцом с именем FName, чтобы принимать имена полей и столбцы для каждого года в исходной таблице.
Function Transpose()
Set db = CurrentDb()
db.Execute ("delete * from TableTranspose")
Set RS = db.OpenRecordset("TableSource")
Set YrList = db.OpenRecordset("select distinct [Yr] from [TableSource] Group by [Yr]")
For Each F In RS.Fields
FN = F.Name
INS = "Insert Into TableTranspose (FName"
SQL = "Select '" & FN & "'"
YrList.MoveFirst
Do While Not YrList.EOF
YR = YrList.Fields("YR").Value
INS = INS & ",[" & YR & "]"
SQL = SQL & ",max(iif(YR=" & YR & ",[" & FN & "])) AS [" & YR & "]"
YrList.MoveNext
Loop
SQL = SQL & " From TableSource"
db.Execute (INS & ") " & SQL)
Next F
MsgBox ("Done")
End Function
Это работает, обрабатывая одно поле за раз, чтобы соответствовать макету желаемого вывода, и циклически перебирая каждый год TableSource, чтобы найти данные, чтобы составить строку в TableTranspose. Не имеет значения, сколько полей есть или что они названы.
Он будет создавать строку в результатах для Года, которая будет избыточной - вы можете удалить ее или добавить логику, чтобы пропустить это поле, если это необходимо.
Кажется, что это хорошо работает с данными за 4 года в вашем образце и должно продлить срок дольше лет. Возможно, вы достигнете предела длины SQL-команды, если в данных слишком много лет, но я думаю, что нет.
Если вы фильтруете записи из TableSource, вы можете добавить предложение WHERE в строке только из db.execute в нижней части.
Доступ к TransFORM не очень интуитивно понятен и прост в использовании, и я не думаю, что вы можете использовать его таким образом. Каждая строка результата должна быть совокупностью вашей таблицы. Я не знаю, как получить предыдущие имена полей в новый столбец.
См. Рабочий пример: TRANSFORM и PIVOT в Access 2013 SQL
То, что вы действительно хотите, - это просто новая презентация существующих данных.
Excel может помочь.
Я никогда не экспортировал PDF из Access, но из Excel легко. Вот пример:
Sub ExportPdf(path As String, Optional openAfter As Boolean)
''calculate best range for print area
Dim lastCol As Integer
Dim firstRow As Integer
Dim lastRow As Integer
lastCol = pt.TableRange2.Columns(pt.TableRange2.Columns.Count).Column
firstRow = pt.TableRange2.Rows(1).Row
lastRow = ms.Cells(pt.TableRange2.Rows.Count * 3, 1).End(xlUp).Row
Worksheets(ContextSheet).PageSetup.PrintArea = Range(Cells(firstRow, 1), Cells(lastRow, lastCol)).Address
Worksheets(ContextSheet).ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
path & "\Area " & getPivotTablePageFilters(getPivotTable()) & ".pdf", Quality:= _
xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, _
OpenAfterPublish:=openAfter
End Sub
Являются ли данные всегда одинаковыми наборами названий полей и лет? Если это так, вы можете использовать запрос UNION, например:
Select "Name" as [FName], max(iif(year="2009",name))as [2009], max(iif(year="2010"
,name)) as [2010], max(iif(year="2011",name)) as [2011], max(iif(year="2012", name)) as [2012] from Table group by FName
Union all Select "Ticker", max(iif(year="2009",ticker)), max(iif(year="2010"
,ticker)), max(iif(year="2011",ticker)), max(iif(year=-"2012",ticker)) from Table group by FName
Union all Select "ID", max(iif(year="2009",id)), max(iif(year="2010"
,id)), max(iif(year="2011",is)), max(iif(year="2012",id)) from Table group by FName
Union all Select "Innovation", max(iif(year="2009",innovation)), max(iif(year="2010"
,innovation)), max(iif(year="2011",innovation)), max(iif(year=-"2012",innovation)) from Table group by FName
Union all Select "Quality", max(iif(year="2009",quality)), max(iif(year="2010"
,quality)), max(iif(year="2011",quality)), max(iif(year=-"2012",quality)) from Table group by FName