【问题标题】:I have a table that looks like:我有一个看起来像的表:
【发布时间】:2018-08-02 07:04:51
【问题描述】:

我有一张桌子有

     Material   90    89     88    87    ….2     1     0
      123456    34    30     26    38     14    12     8
      123457    47    42     33    54     38    27    42

我想把它转换成

     Date        123456     123457              
    Date()-90       34         47
    Date()-89       30         42
    Date()-88       26         33
    Date()-87       38         54
       ….        …………        ………..
    Date()-2        14         38
    Date()-1        12         27
    Date()           8         42

我找到了这个,但正在尝试弄清楚如何使用它:

Private Sub Unpivot_Click()
    Dim x As Integer
    Dim columncount As Integer
    Dim setRST As DAO.Recordset
    Dim sqlstr As String
    Dim qdf As DAO.QueryDef
    Dim fld As DAO.Field

    Set setRST = CurrentDb.OpenRecordset("Select * from TheTable")
columncount = setRST.Fields.Count
    Set qdf = db.CreateQueryDef ("", "Insert Into TheDestination ([Template], [Row], 
[Column], [Result]) VALUES (@Template, @RowNumber, @ColumnNumber, @Result)")
Do While Not setRST.EOF
   qdf.Parameters("@Template") = setRST!Template
   qdf.Parameters("@RowNumber") = setRST!row
   For Each fld In setRST.Fields
       If IsNumeric(fld.Name) Then
            qdf.Parameters("@ColumnNumber") = fld.Name
            qdf.Parameters("@Result") = fld.Value
            qdf.Execute 
       End If
      Next fld
      setRST.MoveNext
   Loop

End Sub

到目前为止,我有:

Public Function Unpivot()

Dim x As Integer
Dim columncount As Integer
Dim setRST As DAO.Recordset
Dim sqlstr As String
Dim qdf As DAO.QueryDef
Dim fld As DAO.Field

Set setRST = CurrentDb.OpenRecordset("SSMaterialByDayQ322")
columncount = setRST.Fields.Count
Set qdf = db.CreateQueryDef("", "Insert INTO SSHistoryQ322 ([Date], [Row], [Column], [Result]) VALUES (@Template, @RowNumber, @ColumnNumber, @Result)")
Do While Not setRST.EOF
   qdf.Parameters("@Template") = setRST!Date
   qdf.Parameters("@RowNumber") = setRST!row
   For Each fld In setRST.Fields
       If IsNumeric(fld.Name) Then
            qdf.Parameters("@ColumnNumber") = fld.Name
            qdf.Parameters("@Result") = fld.Value
            qdf.Execute
       End If
   Next fld
   setRST.MoveNext
Loop

End Function

【问题讨论】:

  • 那么——问题是什么?你在哪一行得到什么信息,或者结果是什么样的?出现该消息时的值是什么?
  • 更多重复,google access query transpose
  • 我怀疑使用 QueryDefs 创建/修改查询能否实现这一点。您需要将数据保存到表中。 Material 有多少个可能的值?表有 255 个字段的限制。
  • 在 Set qdf = db.createquerydef("", "insert into.... 我得到 Object Required。

标签: ms-access unpivot


【解决方案1】:

您可以先进行联合查询

SELECT 'Date()-90' As [Date], Material, [90] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-89' As [Date], Material, [89] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-88' As [Date], Material, [88] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-87' As [Date], Material, [87] As [Value] FROM TheTable
...
UNION ALL
SELECT 'Date()-02' As [Date], Material, [2] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-01' As [Date], Material, [1] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-00' As [Date], Material, [0] As [Value] FROM TheTable

当然,您可以使用 VBA 在循环中创建此查询。将此 SQL 文本存储为查询 qryFlatten

现在我们从这个查询构建一个数据透视查询。这产生了我们的最终结果

TRANSFORM Sum(qryFlatten.Value) AS SumOfValue
SELECT qryFlatten.Date
FROM qryFlatten
GROUP BY qryFlatten.Date
ORDER BY qryFlatten.Date DESC 
PIVOT qryFlatten.Material;

【讨论】:

    【解决方案2】:

    如果表中需要“反透视”的字段不超过 50 个,则 UNION 查询可以将数据重新排列为规范化结构。 UNION 没有查询生成器或向导,必须在 SQL 视图中键入或复制/粘贴。 UNION 的 SELECT 行限制为 50 行。

    SELECT "Date()-90" AS [Date], Material, [90] AS Data FROM SSMaterialByDayQ322
    UNION SELECT "Date()-89", Material, [89] FROM SSMaterialByDayQ322
    UNION SELECT "Date()-88", Material, [88] FROM SSMaterialByDayQ322
    UNION SELECT "Date()-87", Material, [87] FROM SSMaterialByDayQ322
    UNION SELECT "Date()-2", Material, [2] FROM SSMaterialByDayQ322
    UNION SELECT "Date()-1", Material, [1] FROM SSMaterialByDayQ322
    UNION SELECT "Date()-0", Material, [0] FROM SSMaterialByDayQ322;
    

    如果有超过50年的字段,VBA可以将记录写入表,考虑:

    Public Sub Unpivot()
    Dim x As Integer
    Dim rst As DAO.Recordset
    Set rst = CurrentDb.OpenRecordset("SSMaterialByDayQ322")
    Do While Not rst.EOF
       For x = 1 To rst.Fields.Count - 1
            CurrentDb.Execute "INSERT INTO SSHistoryQ322([Date], Material, Data)" & _
                              "VALUES('Date()-" & rst.Fields(x).Name & "', " & rst!Material & ", " & rst.Fields(x) & ")"
       Next
       rst.MoveNext
    Loop
    End Sub
    

    然后,只要唯一的 Material 值不超过 254 个,就从查询或表中构建 CROSSTAB。

    TRANSFORM First(Query1.Data) AS FirstOfData
    SELECT Query1.Date
    FROM Query1
    GROUP BY Query1.Date
    PIVOT Query1.Material;
    

    建议不要使用 Date 作为字段名,因为它是保留字。

    【讨论】:

    • date()-90, date()-89....date()-2, date()-1, date() 表示每行有 91 列值。上次试了个union,确实是50,而且速度很慢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 2023-03-21
    • 2019-06-26
    • 1970-01-01
    相关资源
    最近更新 更多