Конвертировать строки в столбцы - PullRequest
1 голос
/ 14 февраля 2009

Каков наилучший способ сделать это в Access?

Create table tmp
(
  plant int,
  material vchar(20),
  workcenter int,
  setuptime vchar(20)
)

insert into tmp values( 1, mat1, 2, 30)
insert into tmp values( 1, mat1, 3, 30)
insert into tmp values( 1, mat2, 3, 30)
insert into tmp values( 1, mat2, 4, 30)
insert into tmp values( 2, mat1, 4, 30)
insert into tmp values( 2, mat1, 5, 30)

Результат должен выглядеть следующим образом.

Plant  Material  Workcenter1  Setuptime1  Workcenter2  Setuptime2
1      Mat1      2            30          3            30
1      Mat2      3            30          4            30
2      Mat1      4            30          5            30

Я думал, что это может сработать, но должен быть лучший способ.

SELECT t.Plant, 
    t.Material, 
    t.Workcenter as Workcenter1, 
    t.setuptime as SetupTime1
    t2.Workcenter as Workcenter2, 
    t2.setuptime as SetupTime2
FROM tmp t
LEFT JOIN tmp t2
  on t.plant = t2.plant
  and t.material = t2.material

Спасибо большое.

Ответы [ 5 ]

1 голос
/ 16 февраля 2009

Из того, что я понимаю, о проблеме, которую вы хотите решить, я не думаю, что это возможно при использовании стандартного SQL-запроса (по крайней мере, в Access).

Я пытался взломать код, который делает то, что вы хотите (я думаю).

Как его использовать

Просто скопируйте / вставьте приведенный ниже код в модуль VBA.
Из кода или из окна VBA IDE Immediate, если вы хотите проверить его, просто позвоните:

ExpandTable

Предположения

  • таблица temp существует с данными, которые вы хотите расширить, содержащими завод / материал / рабочую станцию ​​/ etc
  • таблица temp не пуста (я пропустил некоторые проверки кода, чтобы избежать раздувания образца).
  • расширенная таблица будет создана в новой таблице с именем result.

Код

Public Sub ExpandTable()

    Dim db As DAO.Database
    Dim rs As DAO.Recordset, rs2 As DAO.Recordset
    Dim td As DAO.TableDef
    Dim fd As DAO.Field
    Dim maxWorkCenters As Integer
    Dim i As Integer
    Dim sql As String

    Set db = CurrentDb

    ' Delete the old result table if there was one '
    On Error Resume Next
    db.TableDefs.Delete "result"
    On Error GoTo 0

    ' Create the result table '
    Set td = db.CreateTableDef("result")
    td.Fields.Append td.CreateField("Plant", dbInteger)
    td.Fields.Append td.CreateField("Material", dbText)
    ' Get the maximum number of workcenters we will need '
    ' for a given Plan/Material combination '
    sql = "SELECT Count(*) FROM Temp GROUP BY Plant, Material"
    Set rs = db.OpenRecordset(sql, dbOpenSnapshot)
    maxWorkCenters = Nz(rs.Fields(0).Value, 0)
    rs.Close
    Set rs = Nothing
    ' Create as many columns as we need to fit all these combinations '
    For i = 1 To maxWorkCenters
        td.Fields.Append td.CreateField("WorkCenter" & i, dbText)
        td.Fields.Append td.CreateField("SetupTime" & i, dbInteger)
    Next i
    db.TableDefs.Append td

    ' Now get the data into the new table '
    Dim lastPlant As Variant, lastMaterial As Variant
    Dim curcol As Integer
    sql = "SELECT Plant, Material, Workcenter, Setuptime FROM Temp ORDER BY Plant, Material, WorkCenter"
    Set rs = db.OpenRecordset(sql, dbOpenSnapshot)
    Set rs2 = db.OpenRecordset("result", dbOpenDynaset)
    With rs
        lastPlant = 0
        lastMaterial = ""
        Do While Not .EOF
            If (Nz(!Plant) <> lastPlant) Or (Nz(!Material) <> lastMaterial) Then
                If rs2.EditMode = dbEditAdd Then
                    ' Save the previously edited record if any '
                    rs2.Update
                End If

                ' Different plant/material, so we add a new result '
                rs2.AddNew
                rs2!Plant = !Plant
                rs2!Material = !Material
                rs2!WorkCenter1 = !WorkCenter
                rs2!SetupTime1 = !Setuptime
                lastPlant = Nz(!Plant)
                lastMaterial = Nz(!Material)
                curcol = 1
            Else
                ' Same plant/material combi, so we fill the next column set '
                curcol = curcol + 1
                rs2.Fields("Workcenter" & curcol).Value = !WorkCenter
                rs2.Fields("SetupTime" & curcol).Value = !Setuptime
            End If
            .MoveNext
        Loop
        If rs2.EditMode = dbEditAdd Then
            ' Save the last result '
            rs2.Update
        End If
    End With

    Set rs2 = Nothing
    Set rs = Nothing
    Set db = Nothing

End Sub

О коде

  • Таблица result создается заново каждый раз, когда вы запускаете ExpandTable.
  • Число дополнительных столбцов WorkCenterX и SetupTimeX адаптируется к фактическому количеству уникальных пар Завод / Материал.
  • Вам придется изменить код в соответствии с вашими потребностями.
  • Вам также придется немного его почистить, так как некоторые вещи, возможно, можно выразить немного лучше, но вы получите шутку.

Тестовая база данных

Вы можете загрузить тестовую базу данных Access 2000 с http://blog.nkadesign.com/wp-content/uploads/SO/SO547777.zip.

В любом случае, надеюсь, что он делает то, что вы хотите, или, по крайней мере, приближает вас.

1 голос
/ 14 февраля 2009

Ваш пример вывода не ясен - я думаю, что он должен выглядеть следующим образом:

Plant | Mat  | Wkcntr1 | STime1 | Wkcntr2 | STime2 
1     | Mat1 | 2       | 30     | 3       | 30 
1     | Mat2 | 3       | 30     | 4       | 30 
2     | Mat1 | 4       | 30     | 5       | 30 

Я бы сказал, что стол не идеально накрыт. Не похоже, что у него есть первичный ключ, поэтому неясно, какая запись принадлежит 1 столбцу, а какая - 2.

Я бы добавил дополнительное поле для RecordNumber (это 1 или 2), тогда у вас есть первичный ключ Plant, Material и RecordNumber.

Ваш запрос будет выглядеть так:

SELECT tmp.plant, tmp.material, tmp.workcenter AS W1, tmp.setuptime AS S1, tmp_1.workcenter AS W2, tmp_1.setuptime AS S2
FROM tmp INNER JOIN tmp AS tmp_1 ON (tmp.material = tmp_1.material) AND (tmp.plant = tmp_1.plant)
WHERE (((tmp.recordNum)=1) AND ((tmp_1.recordNum)=2));

Это будет работать только с ограниченным (и уже известным) числом числовых вещей (независимо от того, что представляют 1 и 2).

1 голос
/ 14 февраля 2009

Вы пробовали Crosstab Query?

EDIT

(я переворачиваюсь лучше после переформатирования вашего вопроса)

Ваше решение будет почти работать. Но то, что вы получите, будет иметь двойные записи (как это):

Plant  Material  Workcenter1  Setuptime1  Workcenter2  Setuptime2
1      Mat1      2            30          2            30
1      Mat1      2            30          3            30
1      Mat1      3            30          2            30
1      Mat1      3            30          3            30
1      Mat2      3            30          4            30
1      Mat2      3            30          3            30
1      Mat2      4            30          3            30
1      Mat2      4            30          4            30
2      Mat1      4            30          5            30
2      Mat1      4            30          4            30
2      Mat1      5            30          5            30
2      Mat1      5            30          4            30

А если у вас более двух рабочих центров, то становится еще хуже.

Так что вам нужен индикатор столбца

Create table tmp
(
  plant int,
  material vchar(20),
  workcenter int,
  setuptime vchar(20),
  myCol int
);

(кстати, vchars не будет работать в ms-access / Jet ... хотя chars будет работать)

insert into tmp values( 1, mat1, 2, 30, 1);
insert into tmp values( 1, mat1, 3, 30, 2);
insert into tmp values( 1, mat2, 2, 30, 1);
insert into tmp values( 1, mat2, 3, 30, 2);
insert into tmp values( 2, mat1, 4, 30, 1);
insert into tmp values( 2, mat1, 5, 30, 2);

SELECT tmp.plant, tmp.material, tmp.workcenter,   tmp.setuptime,
                                tmp_1.workcenter, tmp_1.setuptime
FROM tmp INNER JOIN tmp AS tmp_1 ON (tmp.material = tmp_1.material)
    AND (tmp.plant = tmp_1.plant)
WHERE   (((tmp.myCol)=1)
    AND ((tmp_1.myCol)=2));

Конечно, если вы можете редактировать исходную таблицу, возможно, вы захотите просто добавить второй столбец Workcenter и Setuptime,

0 голосов
/ 14 февраля 2009

В мастере запросов есть опция кросс-таблицы, которая размещает вашу таблицу горизонтально. Разве это не то, что вы ищете?

0 голосов
/ 14 февраля 2009

Я недостаточно хорошо знаю синтаксис доступа, чтобы дать вам полный ответ, но для помощи в ваших собственных расследованиях я могу вам сказать, что то, что вы пытаетесь сделать, называется запросом "перекрестная таблица" или "сводная точка". 1001 *

Использование этих ключевых слов в Google должно помочь вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...