Sql server 在SQL Server中将包含不同数据的列转换为多行
我有一个从excel表格导入的表格。我对高级SQL相当陌生 第一列(账号)按顺序包含对应于该列前3行的账号、账号日期和名称。该列的下3行包含不同用户的相同类型的信息 第二列(Amount)包含Amount、Percentage Increase、Amount Due,它们对应于该列的下3行,依此类推 导入的当前表结构: 我想知道如何将这些值透视到具有以下结构的不同表中: 账号、账户日期、姓名、金额、增加百分比、到期金额 预期产出表: 我尝试过使用交叉应用程序,但没有成功。 我还尝试在SQLServer中使用PIVOT。然而,我遇到的示例和解决方案都有包含相同类型数据的列Sql server 在SQL Server中将包含不同数据的列转换为多行,sql-server,excel,Sql Server,Excel,我有一个从excel表格导入的表格。我对高级SQL相当陌生 第一列(账号)按顺序包含对应于该列前3行的账号、账号日期和名称。该列的下3行包含不同用户的相同类型的信息 第二列(Amount)包含Amount、Percentage Increase、Amount Due,它们对应于该列的下3行,依此类推 导入的当前表结构: 我想知道如何将这些值透视到具有以下结构的不同表中: 账号、账户日期、姓名、金额、增加百分比、到期金额 预期产出表: 我尝试过使用交叉应用程序,但没有成功。 我还尝试在SQLS
SELECT [Account Number] FROM SourceTable AS T1
PIVOT
(
-- AGGREGATE FUNCTION
FOR
[Account Number]
IN ( [Account Number],[Date], [Name] )
)
AS T2
请让我知道如何进行这项工作 至少可以说,这是一个非常可怕的数据结构。您有三行需要成为一行。这充其量是丑陋的。更糟糕的是,您必须至少在开始时将所有内容存储为varchar,因为您有各种各样的数据类型。您可以在这里使用一些条件聚合。第一步是以我们可以使用的格式提供样本数据
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
SomethingID int identity
, SomeValue varchar(50)
, SomeOtherValue int
)
insert #Something values
('1111', 10000)
, ('10/31/2017', 1)
, ('John Smith', 100)
, ('2222', 20000)
, ('10/31/2017', 1)
, ('Jane Doe', 200)
;
现在我们得有点棘手了。我将其分为多个步骤,以便您可以看到发生了什么。第一步是为每组三行分配一个组号。然后我们需要对每个组中的每一行重新编号,以便知道给定行属于组中的哪一行。这就是为什么有一个排序列是如此重要的原因。最后一步是使用条件聚合将此灾难解析为所需的列
with SortedValues as
(
select *
, row_number() over(order by SomethingID) as RowNum
, case SomethingID % 3 when 1 then (SomethingID + 2) / 3
when 2 then (SomethingID + 1) / 3
when 0 then SomethingID / 3
end as GroupNumber
from #Something
)
, GroupedOrdering as
(
select *
, ROW_NUMBER() over(partition by GroupNumber order by RowNum) as GroupRowNum
from SortedValues
)
select AccountNumber = max(case when GroupRowNum = 1 then SomeValue end)
, MyDate = max(case when GroupRowNum = 2 then SomeValue end)
, AccountName = max(case when GroupRowNum = 3 then SomeValue end)
, Amount = max(case when GroupRowNum = 1 then SomeOtherValue end)
, MyPercentage = max(case when GroupRowNum = 2 then SomeOtherValue end)
, AmountDue = max(case when GroupRowNum = 3 then SomeOtherValue end)
from GroupedOrdering
group by GroupNumber
如果可能的话,我建议更改这个表结构,因为这是一个噩梦。这里还有一些工作要做,因为数据类型到处都是。希望这足够接近您可以完成此操作。至少可以说,这是一个非常糟糕的数据结构。您有三行需要成为一行。这充其量是丑陋的。更糟糕的是,您必须至少在开始时将所有内容存储为varchar,因为您有各种各样的数据类型。您可以在这里使用一些条件聚合。第一步是以我们可以使用的格式提供样本数据
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
SomethingID int identity
, SomeValue varchar(50)
, SomeOtherValue int
)
insert #Something values
('1111', 10000)
, ('10/31/2017', 1)
, ('John Smith', 100)
, ('2222', 20000)
, ('10/31/2017', 1)
, ('Jane Doe', 200)
;
现在我们得有点棘手了。我将其分为多个步骤,以便您可以看到发生了什么。第一步是为每组三行分配一个组号。然后我们需要对每个组中的每一行重新编号,以便知道给定行属于组中的哪一行。这就是为什么有一个排序列是如此重要的原因。最后一步是使用条件聚合将此灾难解析为所需的列
with SortedValues as
(
select *
, row_number() over(order by SomethingID) as RowNum
, case SomethingID % 3 when 1 then (SomethingID + 2) / 3
when 2 then (SomethingID + 1) / 3
when 0 then SomethingID / 3
end as GroupNumber
from #Something
)
, GroupedOrdering as
(
select *
, ROW_NUMBER() over(partition by GroupNumber order by RowNum) as GroupRowNum
from SortedValues
)
select AccountNumber = max(case when GroupRowNum = 1 then SomeValue end)
, MyDate = max(case when GroupRowNum = 2 then SomeValue end)
, AccountName = max(case when GroupRowNum = 3 then SomeValue end)
, Amount = max(case when GroupRowNum = 1 then SomeOtherValue end)
, MyPercentage = max(case when GroupRowNum = 2 then SomeOtherValue end)
, AmountDue = max(case when GroupRowNum = 3 then SomeOtherValue end)
from GroupedOrdering
group by GroupNumber
如果可能的话,我建议更改这个表结构,因为这是一个噩梦。这里还有一些工作要做,因为数据类型到处都是。希望这段距离足够近,您可以完成此任务。您好,欢迎来到SO。我们需要更多的细节,因为这是相当模糊的。这是一个很好的起点。我为此道歉。我将相应地更新我的问题。谢谢。我看了一会儿你把你的样本数据作为文本而不是图像发布。那会好得多。这就是我所看到的挑战。表中没有任何指示顺序的内容,因此不知道这三行是一组逻辑信息的一部分。根据定义,表是无序集。如果您甚至包括一个标识列,您至少可以确定哪些行放在一起,尽管这相当脆弱。如果没有订购栏,这是不可能的。感谢您的快速回复。我可以在源表中包含标识列。我该怎么做?@SeanLange你能找到一个方法来回答这个问题吗?欢迎来到SO。我们需要更多的细节,因为这是相当模糊的。这是一个很好的起点。我为此道歉。我将相应地更新我的问题。谢谢。我看了一会儿你把你的样本数据作为文本而不是图像发布。那会好得多。这就是我所看到的挑战。表中没有任何指示顺序的内容,因此不知道这三行是一组逻辑信息的一部分。根据定义,表是无序集。如果您甚至包括一个标识列,您至少可以确定哪些行放在一起,尽管这相当脆弱。如果没有订购栏,这是不可能的。感谢您的快速回复。我可以在源表中包含标识列。我该怎么做?@SeanLange你能找到一个方法来回答这个问题吗?谢谢你。这很有帮助。我知道数据很难看,很难转换。我将尝试您的解决方案,并尽快更新结果。谢谢您的回答。我按照建议将它们分组,然后将账号、日期和名称的行导入到3个单独的表中。然后,我将账号插入到最后一个表中,并根据组Id更新其余字段。谢谢。这很有帮助。我知道数据很难看,很难转换。我将尝试您的解决方案,并尽快更新结果。谢谢您的回答。我按照建议将它们分组,然后将账号、日期和名称的行导入到3个单独的表中。然后,我将账号插入到最后一个表中,并根据组Id更新其余字段。