透视和分区查询以获取名称
Posted
技术标签:
【中文标题】透视和分区查询以获取名称【英文标题】:Pivoting and partitioning Query to get Names 【发布时间】:2018-11-22 01:16:23 【问题描述】:我尝试了下面的 HackerRank 问题,其中名称必须以职业为中心。
https://www.hackerrank.com/challenges/occupations/problem
我找到了一个解决方案,但不明白它具体是如何工作的,为什么在对名称取最大值时其他名称会在结果中返回。
表:
CREATE TABLE Occupations
(
Name varchar(25),
Occupation varchar(1000)
)
INSERT INTO Occupations VALUES('Samantha', 'Doctor')
GO
INSERT INTO Occupations VALUES('Julia', 'Actor')
GO
INSERT INTO Occupations VALUES('Maria', 'Actor')
GO
INSERT INTO Occupations VALUES('Meera', 'Singer')
GO
INSERT INTO Occupations VALUES('Ashley', 'Professor')
GO
INSERT INTO Occupations VALUES('Ketty', 'Professor')
GO
INSERT INTO Occupations VALUES('Christeen', 'Singer')
GO
INSERT INTO Occupations VALUES('Jane', 'Actor')
GO
INSERT INTO Occupations VALUES('Jenny', 'Doctor')
GO
INSERT INTO Occupations VALUES('Priya', 'Singer')
GO
解决方案:
SELECT [Doctor], [Professor], [Singer],[Actor]
FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY Occupation ORDER BY Name ASC) AS RowNumber, *
FROM Occupations) as tempTable
PIVOT
(
MAX(Name) FOR OCCUPATION IN ([Doctor], [Professor], [Singer], [Actor])
) AS pivotTable
所以我理解这个查询被执行的方式是,行被按名称排序的职业分区,然后最大名称在职业上进行旋转。那么查询如何仍然按职业返回其他名称?
【问题讨论】:
PIVOT 的工作方式是对不在 PIVOT 中的其余列进行分组。在这里,您分配了按职业划分的 row_number(),因此职业中的每个名称都分配了一个数字(1、2、3 等...)。枢轴将找到行号 = 1 的每个职业的 max(name),rownumber = 2 的每个职业的 max(name) 等等......本质上,row_number() 窗口函数将名称分成不同的组,所有结果返回。 在没有 PIVOT 的情况下编写它可能会有所帮助。例如,SELECT [Doctor] = MAX(CASE WHEN Occupation = 'Doctor' THEN Name END), [Professor] = MAX(CASE WHEN Occupation = 'Professor' THEN Name END), [Singer] = MAX(CASE WHEN Occupation = 'Singer' THEN Name END), [Actor] = MAX(CASE WHEN Occupation = 'Actor' THEN Name END) FROM (SELECT *, RowNumber = ROW_NUMBER() OVER (PARTITION BY Occupation ORDER BY Name) FROM Occupations) AS O GROUP BY RowNumber;
这是一个很好的解释。我没有意识到 PIVOT 中未包含在 PIVOT 中的列上的 PIVOT 组。
您编写的透视查询和分组查询的工作方式是否相同?
差不多,是的。如果您同时运行这两个查询,那么您可能会看到类似的执行计划。但无论如何,它们背后的原理都是一样的。如果您寻找如何在 SO 上的 SQL Server 中进行透视的示例,您会发现许多使用 CASE
和聚合的类似示例。
【参考方案1】:
/使用 MS SQL 服务器/
SELECT [Doctor],[Professor],[Singer],[Actor] from (select row_number() over (partition by occupation order by Name)rownumber,name,occupation from occupations group by occupation,name)as table2 pivot(max(name) for occupation in ([Doctor],[professor],[Singer],[Actor])) as tab1 order by rownumber
【讨论】:
您能否edit 提供更好的缩进以提高可读性?以上是关于透视和分区查询以获取名称的主要内容,如果未能解决你的问题,请参考以下文章