Я хочу транспонировать строки в столбцы в ms-access

0

Мне нужно транспонировать строки в столбцы в базе данных 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

  • 1
    Неуклюжий обходной путь - скопировать его в Excel, использовать копирование / вставку транспонирования, а затем либо опубликовать PDF-файл из Excel, либо скопировать транспонированную таблицу обратно в Access. Кроме того, я не думаю, что понимаю желаемую таблицу - как будут выглядеть следующие 4 строки, то есть для Name = "ABC"? Будет ли это добавить новые строки или новые столбцы в нужную таблицу?
  • 0
    Таким образом, я бы просто отобразил одну компанию, которую я выберу из списка, для которой я бы обновил код как Ticker = [Forms]! [ComSearch_frm]! [Search_lbx] .Value. Поэтому моей желаемой таблицей будет публикация только одной информации о компании. Год мудрый.
Показать ещё 2 комментария
Теги:
sql-server
ms-access

3 ответа

1

Это скрипт 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 в нижней части.

  • 0
    Один последний комментарий - в выходной таблице каждый столбец может иметь только один тип данных, поэтому я предположил, что все исходные данные являются текстовыми, а поля в TableTranspose будут текстовыми. Вам может понадобиться вставить некоторые кавычки (одинарные кавычки) в сборку команды SQL, если в TableSource есть числовые данные, кроме года.
  • 0
    Большое спасибо. Но я получаю ошибку Слишком мало параметров. Ожидаемый 1. Если мы попытаемся отладить, я перейду в db.Execute (INS & ")" & SQL) Заранее спасибо.
Показать ещё 1 комментарий
1

Доступ к 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
  • 0
    в приведенном выше коде pt является сводной таблицей
  • 0
    Мастер Crosstab существует по причине, и он довольно интуитивно понятен. Но, как вы говорите, это не сработает для требований OP - можно PIVOT для одного столбца («заголовка столбца»), но не для всех.
Показать ещё 7 комментариев
0

Являются ли данные всегда одинаковыми наборами названий полей и лет? Если это так, вы можете использовать запрос 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
  • 0
    Да, имена столбцов являются фиксированными, и даже годы с 2005 по 2015 год. У меня всего 83 параметра, я думаю, что MS Access имеет ограничения оператора UNION. Могу ли я сделать это с помощью UNION?
  • 0
    Для такого количества полей я бы сделал это в vba - я подумаю об этом и отправлю другой ответ, если смогу. Я не знаю, сможет ли UNION справиться с таким количеством источников, но запрос будет ужасным. Что вы думаете о решении Excel, которое я отметил в комментариях и которое Андре поддержал?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню