Sql 对列和行进行分组和切换
我不知道这是否会被正式称为支点,但我想要的结果是:Sql 对列和行进行分组和切换,sql,sql-server,tsql,pivot,sql-server-2012,Sql,Sql Server,Tsql,Pivot,Sql Server 2012,我不知道这是否会被正式称为支点,但我想要的结果是: +------+---------+------+ | Alex | Charley | Liza | +------+---------+------+ | 213 | 345 | 1 | | 23 | 111 | 5 | | 42 | 52 | 2 | | 323 | | 5 | | 23 | | 1 | | 324 |
+------+---------+------+
| Alex | Charley | Liza |
+------+---------+------+
| 213 | 345 | 1 |
| 23 | 111 | 5 |
| 42 | 52 | 2 |
| 323 | | 5 |
| 23 | | 1 |
| 324 | | 5 |
+------+---------+------+
我的输入数据如下表所示:
+-----+---------+
| Apt | Name |
+-----+---------+
| 213 | Alex |
| 23 | Alex |
| 42 | Alex |
| 323 | Alex |
| 23 | Alex |
| 324 | Alex |
| 345 | Charley |
| 111 | Charley |
| 52 | Charley |
| 1 | Liza |
| 5 | Liza |
| 2 | Liza |
| 5 | Liza |
| 1 | Liza |
| 5 | Liza |
+-----+---------+
因为我有大约100个名字,我不想做像这样的子查询吨
select null, null, thirdcolumn from...
select null, seconcolumn from...
select firstcolumn from...
有没有一种方法可以通过PIVOT或其他方式实现这一点?您可以通过dynamic PIVOT和ROW\u NUMBER功能实现这一点:
DECLARE @cols AS VARCHAR(1000),
@query AS VARCHAR(8000)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(Name)
FROM (SELECT DISTINCT Name
FROM #test
)sub
ORDER BY Name
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)')
,1,1,'')
PRINT @cols
SET @query = '
WITH cte AS (SELECT DISTINCT *
FROM #test)
,cte2 AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Apt)RowRank
FROM cte)
SELECT *
FROM cte2
PIVOT (max(Apt) for Name in ('+@cols+')) p
'
EXEC (@query)
编辑:如果不希望列表不同,请删除上面的第一个cte,如果希望保持任意顺序,请更改顺序,选择1:
最后,如果不想在结果中使用RowRank字段,只需在SELECT中重新使用@cols变量:
您可以使用“动态轴”和“行数”功能执行此操作:
DECLARE @cols AS VARCHAR(1000),
@query AS VARCHAR(8000)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(Name)
FROM (SELECT DISTINCT Name
FROM #test
)sub
ORDER BY Name
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)')
,1,1,'')
PRINT @cols
SET @query = '
WITH cte AS (SELECT DISTINCT *
FROM #test)
,cte2 AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Apt)RowRank
FROM cte)
SELECT *
FROM cte2
PIVOT (max(Apt) for Name in ('+@cols+')) p
'
EXEC (@query)
编辑:如果不希望列表不同,请删除上面的第一个cte,如果希望保持任意顺序,请更改顺序,选择1:
最后,如果不想在结果中使用RowRank字段,只需在SELECT中重新使用@cols变量:
哦,这有点痛苦,但是你可以用SQL来做。您正在尝试连接列
select seqnum,
max(case when name = 'Alex' then apt end) as Alex,
max(case when name = 'Charley' then apt end) as Charley,
max(case when name = 'Liza' then apt end) as Liza
from (select t.*, row_number() over (partition by name order by (select NULL)) as seqnum
from t
) t
group by seqnum
order by seqnum;
请注意:不能保证每列中的原始顺序相同。正如您所知,SQL表本质上是无序的,因此您需要一个列来指定顺序
要处理多个名称,我只需使用以下查询获取列表:
select distinct 'max(case when name = '''+name+''' then apt end) as '+name+','
from t;
然后将结果复制到查询中。哦,这有点麻烦,但您可以使用SQL来完成。您正在尝试连接列
select seqnum,
max(case when name = 'Alex' then apt end) as Alex,
max(case when name = 'Charley' then apt end) as Charley,
max(case when name = 'Liza' then apt end) as Liza
from (select t.*, row_number() over (partition by name order by (select NULL)) as seqnum
from t
) t
group by seqnum
order by seqnum;
请注意:不能保证每列中的原始顺序相同。正如您所知,SQL表本质上是无序的,因此您需要一个列来指定顺序
要处理多个名称,我只需使用以下查询获取列表:
select distinct 'max(case when name = '''+name+''' then apt end) as '+name+','
from t;
然后将结果复制到查询中。还有一个类似的问题,不过对于100个名称,动态查询可能是您的朋友。谢谢!我很想看到一个解决这个问题的动态sql解决方案。这是一个类似的问题,尽管对于100个名字,动态查询可能是你的朋友。谢谢!我希望看到一个动态sql解决方案来解决这个问题