Microsoft SQL Server:向行中添加新列而不是重复的值
以下是我目前的情况: 我看到了一个长长的数据列表,其中包含名称和值,以及相应的值ID。ID的数量可以根据显示的数据而变化,但对于整个集合来说是恒定的。此集合的每个名称正好有2个值。问题是,名称重复,但ID不重复。我的问题就变成了, 如何转换如下所示的表:Microsoft SQL Server:向行中添加新列而不是重复的值,sql,sql-server,Sql,Sql Server,以下是我目前的情况: 我看到了一个长长的数据列表,其中包含名称和值,以及相应的值ID。ID的数量可以根据显示的数据而变化,但对于整个集合来说是恒定的。此集合的每个名称正好有2个值。问题是,名称重复,但ID不重复。我的问题就变成了, 如何转换如下所示的表: Name | ID | Value Sam | 1 | 15 Sam | 2 | 6 Bob | 1 | 9 Bob | 2 | 11 Name | Value1 | Value2 Sam |
Name | ID | Value
Sam | 1 | 15
Sam | 2 | 6
Bob | 1 | 9
Bob | 2 | 11
Name | Value1 | Value2
Sam | 15 | 6
Bob | 9 | 11
更像这样:
Name | ID | Value
Sam | 1 | 15
Sam | 2 | 6
Bob | 1 | 9
Bob | 2 | 11
Name | Value1 | Value2
Sam | 15 | 6
Bob | 9 | 11
注意:我发现很难找到这个问题的标题。您可以使用pivot作为示例。请看以下代码片段:
SELECT pvt.Name, pvt.[1] as Value1, pvt.[2] as Value2
FROM yourTable
PIVTO (
MAX(Value)
FOR id IN([1],[2])
) as pvt
您只需将附加id添加到IN和SELECT中
如果您需要动态轴,可以在此处使用此轴:
DECLARE @sql nvarchar(max), @columnlist nvarchar(max)
SELECT @columnlist =
COALESCE(@columnlist + N',['+CONVERT(nvarchar(max),cols.id)+']',
N'['+CONVERT(nvarchar(max),cols.id)+']'
)
FROM (SELECT DISTINCT id FROM yourTable) as cols
-- this is your part
SET @sql = N'
SELECT pvt.*
FROM yourTable
PIVTO (
MAX(Value)
FOR id IN('+@columnlist+')
) as pvt'
EXEC(@sql)
如果可以确保集合只有两个值,并且这些值的ID始终为1或2,则可以执行以下操作:
CREATE TABLE #Table (Name VARCHAR(5), ID INT, Value INT)
INSERT INTO #Table VALUES ('Sam', 1, 15), ('Sam', 2, 6), ('Bob', 1, 9), ('Bob', 2, 11)
SELECT t.Name,
t.Value AS Value1,
t2.Value AS Value2
FROM #Table t
INNER JOIN #Table t2 ON t2.Name = t.Name AND t2.ID = 2
WHERE t.ID = 1
DROP TABLE #Table
请注意,临时表仅用于说明结果。重要的是SELECT语句
这会将表连接到自身以获取Value2的值。您需要的是一个PIVOT查询。根据您的数据集中有多少个名称,以及您是否提前知道它们,您可能需要一个动态轴心 Pivot查询可能有点混乱。但这里有两个示例说明如何构建动态透视查询。第二个问题是另一个堆栈溢出问题,可能比第一个问题更适合您的情况 编辑:具体示例
-- DROP TABLE #MyTable
-- CREATE TABLE #MyTable( name varchar(10), ID int, value int );
INSERT #MyTable VALUES ('Sam', 1, 15);
INSERT #MyTable VALUES ('Sam', 2, 6);
INSERT #MyTable VALUES ('Bob', 1, 9);
INSERT #MyTable VALUES ('Bob', 2, 11);
-- INSERT #MyTable VALUES ('Sam', 3, 1);
-- INSERT #MyTable VALUES ('Bob', 3, 2);
DECLARE @cols NVARCHAR(2000)
DECLARE @query NVARCHAR(4000)
SELECT @cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT
'],[' + CONVERT(varchar(5), t.ID )
FROM #MyTable AS t
--ORDER BY '],[' + t.ID
FOR XML PATH('')
), 1, 2, '') + ']'
--SELECT @cols
SET @query = N'SELECT name,'+ @cols +' FROM
(SELECT t1.name, t1.ID, t1.Value FROM #MyTable AS t1) p
PIVOT (MAX([Value]) FOR ID IN ( '+ @cols +' ))
AS pvt;'
EXECUTE(@query)
您需要重写此查询以添加/删除连接操作,具体取决于与每个名称关联的值的数量。我认为pivot是解决整个问题的一个更稳健的解决方案,尽管这个解决方案在提供的具体示例中足够有效。我同意pivot是一个更合适的解决方案,但是当OP指示只有两个值时,这将执行得更快。实际上,OP指示,ID的数量可能因提供的数据而异,但本例中每个名称正好有2个值。@死区在这种情况下,PIVOT也不能解决问题,因为它会将每个单独的ID透视到它自己的列中。我很困惑。。。这不正是OP想要的吗?每个ID都成为它自己的列,列中列出了值。这也正是你的查询所做的,只是它被硬编码为值1和2。这似乎正是我想要的。我尝试使用这段代码,每个名称有3个和4个值,效果非常好。谢谢@DeadZone