我想制作一个以这种格式呈现/分析我的数据的表格:
按月的价值
ID Jan 09 Feb 09 Mar 09 Apr 09 May 09 Jun 09 Jul 09
1234 10 0 0 0 5 10 8
2345 0 0 0 0 7 0 5
3456 5 0 0 7 0 0 3
我已经按照以下格式获得了数据(第一列中的月份,然后是第二列中的值),其中缺少的任何月份为“0”。如何在MS Access或Excel中操作它?
ID
1234 01-01-2009 10 01-06-2009 20 01-07-2009 15
2345 01-02-2009 15 01-04-2009 20 01-06-2009 10 01-07-2009 16
3456 01-03-2009 8 01-04-2009 30 01-07-2009 4
数据按月运行六年,因此手动操作非常复杂。
答案 0 :(得分:1)
这是我提出的解决方案,如果您可以使用SQL,则使用SQL。我通常使用MS SQL Server 2008R2,因此我将在此答案中使用的查询将在那里工作,而我不能保证它在不同的SQL引擎上工作。
首先,我创建了表并使用您在问题中的数据,我有:
这里我们有一个名为“#' SO'的数据库,其中有一个名为' dbo.Test'以及描述的列和数据类型。 nvarchar(10)表示列包含最大长度为10的基于文本的值。结尾处的null表示列中也可以有空值(类似于空值)。
所以我所做的不是问题就是提供一些标题,第一列是' ID'以及随后的所有交替的' DaX'和' VaX' (X表示一个数字,而“Da”表示日期,“Va”表示数值')。请注意,将值导入为数字实际上更好(我忘了将它们导入为此并决定保留它,以表明即使这样也可以。)
所以下面的查询是非常先进的(至少在我看来),因为它从变量构建了一个查询,我自己必须看一下才能使语法正确并且代码正常工作。要运行它,您需要创建一个新查询,粘贴下面的代码并执行代码。
-- Use the database named SO
USE SO
-- Create some variables
DECLARE @Script VARCHAR(MAX), -- The variable to hold the final script
@Dates VARCHAR(MAX), -- This will hold the column names of date columns
@Values VARCHAR(MAX) -- This will hold the column names of value columns
-- This is a temporary table holding the column number and column
-- names for date columns.
;WITH [Cols] AS (
-- Get column number and column names from sys.table
SELECT
ROW_NUMBER() OVER(ORDER BY name) AS [RowID],
[name]
FROM
sys.columns
-- Where the object is the data table called Test
WHERE
[object_id] = object_id('Test')
-- And where the column name begins with 'da' (case insensitive)
AND
[name] LIKE 'da%'
),
-- Another temporary table that uses the above to make a comma
-- separated list of all date column names. It uses recursion to do that
[Concted] AS (
-- Get the first column number and name from the above temp table
SELECT
[RowID],
CAST([name] AS VARCHAR(MAX)) AS [name]
FROM
[Cols]
WHERE
[RowID] = 1
-- Add it to...
UNION ALL
-- The current column name, a comma and another column name
SELECT
[Cols].[RowID],
CAST([Concted].[name] + ',' + [Cols].[name] AS VARCHAR(MAX))
FROM
[Concted]
JOIN
[Cols]
-- That other column name determined by taking the current row number and the next
ON
[Cols].[RowID] = [Concted].[RowID] + 1
)
-- Get the first row from the second temp table (which now contains all
-- dates separated by comma and store in @Dates
SELECT
@Dates = [name]
FROM
[Concted]
WHERE
[RowID] = (SELECT MAX([RowID]) FROM Concted)
-- Do the same for values
;WITH [Cols] AS (
SELECT
ROW_NUMBER() OVER(ORDER BY name) AS [RowID],
[name]
FROM
sys.columns
WHERE
[object_id] = object_id('Test')
AND
[name] LIKE 'va%'
),
[Concted] AS (
SELECT
[RowID],
CAST([name] AS VARCHAR(MAX)) AS [name]
FROM
[Cols]
WHERE
[RowID] = 1
UNION ALL
SELECT
[Cols].[RowID],
CAST([Concted].[name] + ',' + [Cols].[name] AS VARCHAR(MAX))
FROM
[Concted]
JOIN
[Cols]
ON
[Cols].[RowID] = [Concted].[RowID] + 1
)
SELECT
@Values = [name]
FROM
[Concted]
WHERE
[RowID] = (SELECT MAX([RowID]) FROM Concted)
-- Here we build the 'skeleton' of the main script, and it uses the two
-- lists of columns we built earlier above.
SET @Script = '
-- Select the ID, dates and values
SELECT
[ID],
[Dates],
[Values]
FROM
Test
-- Unpivot once on dates
UNPIVOT (
[Dates] FOR [Date] IN ('+@Dates+')
) AS u1
-- Unpivot a second one for values
UNPIVOT (
[Values] FOR [Value] IN ('+@Values+')
) AS u2
-- Where the column number for date and value match and
-- neither dates nor values are blanks
WHERE
SUBSTRING([Date],3,LEN([Date])) = SUBSTRING([Value],3,LEN([Value]))
AND
ISNULL([Dates],'''') <> ''''
AND
ISNULL([Values],'''') <> ''''
'
-- Execute the above script
EXEC (@Script)
我在代码中尽可能多地解释了注释(以--
开头的行)。一旦运行,我从上面得到以下内容:
ID Dates Values
1234 01/01/2009 10
1234 01/06/2009 20
1234 01/07/2009 15
2345 01/02/2009 15
2345 01/04/2009 20
2345 01/06/2009 10
2345 01/07/2009 16
3456 01/03/2009 8
3456 01/04/2009 30
3456 01/07/2009 4
获得上表后,我们可以将其复制/粘贴到Excel中以运行数据透视表,只需点击几下,我们就可以获得: