【问题标题】:Using PIVOT with SQL Server without Aggregate function在没有聚合函数的 SQL Server 中使用 PIVOT
【发布时间】:2020-06-22 13:31:46
【问题描述】:

我坚持在一个简单的例子中使用PIVOT(我将在下面完整给出)。完全披露,我从https://www.hackerrank.com/ 得到这个。我之所以选择它,正是因为我想更熟悉PIVOT,这看起来像是一个简单的例子!我看过很多关于这个主题的帖子,并且一直在用这个来抄袭:https://social.msdn.microsoft.com/Forums/sqlserver/en-US/b76a4668-d0c3-4c51-8d86-117d5c181e69/pivot-without-aggregate-function?forum=transactsql,但似乎无法把事情搞定。这是表格:

 TABLE OCCUPATIONS

Name    Occupation
Samantha    Doctor
Julia   Actor
Maria   Actor
Meera   Singer
Ashley  Professor
Ketty   Professor
Christeen   Professor
Jane    Actor
Jenny   Doctor
Priya   Singer

任务是使输出具有Doctor、Professor、Singer 或Actor 列(按此顺序)。如果您用完一列或多列的数据,请输入NULL。这是预期的输出(直接从网站复制)。

Jenny    Ashley     Meera  Jane
Samantha Christeen  Priya  Julia
NULL     Ketty      NULL   Maria

顺便说一句,他们似乎想要没有列标题的结果(我不确定!)。

这是我尝试过的最新版本:

SELECT [Doctor], [Professor],[Singer], [Actor]
FROM
(SELECT [Name], [Occupation] from OCCUPATIONS) as pvtsource
PIVOT
( MAX([Name]) FOR [Occupation] IN ([Doctor], [Professor],[Singer], [Actor]) ) AS p

它产生:

     Doctor Professor   Singer  Actor
Samantha    Ketty   Priya   Maria

我对这个不正确的结果并不感到惊讶。毕竟,我在查询中确实说过MAX。我假设它只是根据字母排序为每个职业选择MAX 名称。例如,如果您基于字母表,玛丽亚是比 Julia 或 Jane 更“大”的演员。但是当我删除MAX 时,我收到一个错误(“语法不正确...”)。如何做到这一点?

谢谢! 奖金问题 1.好,温柔,文章给PIVOT?我显然还没有通过我的厚脑袋得到它。最终,我确实希望能够在我 SUMMAX 的地方进行更复杂的旋转。 2.如何显示没有列标题的结果? 3. 如果有简单的方法,我也有兴趣在没有PIVOT 的情况下如何做到这一点。

【问题讨论】:

  • 透视一种聚合形式。
  • 这能回答你的问题吗? TSQL Pivot without aggregate function。就个人而言,我建议使用条件聚合/“Cross-tab”answer
  • @Larnu。我以前看过那个链接。要么它没有回答我的问题,要么我太密集而看不到它。接受的答案谈到使用“MAX”,正如我提到的,我在使用 MAX(或 MIN)时得到了错误的结果。

标签: sql-server tsql pivot pivot-table


【解决方案1】:

您需要使用 X 轴、Y 轴和值来“馈送”枢轴。我们通过dense_rank()创建一个行键

示例

Declare @YourTable Table ([Name] varchar(50),[Occupation] varchar(50))  Insert Into @YourTable Values 
 ('Samantha','Doctor')
,('Julia','Actor')
,('Maria','Actor')
,('Meera','Singer')
,('Ashley','Professor')
,('Ketty','Professor')
,('Christeen','Professor')
,('Jane','Actor')
,('Jenny','Doctor')
,('Priya','Singer')

Select * 
 from (Select *
             ,RN = dense_rank() over (partition by occupation order by name)
        From  @YourTable
      ) src
 Pivot (max(Name) for Occupation in ([Doctor], [Professor],[Singer], [Actor]) ) pvt 

退货

RN  Doctor      Professor   Singer  Actor
1   Jenny       Ashley      Meera   Jane
2   Samantha    Christeen   Priya   Julia
3   NULL        Ketty       NULL    Maria

注意:

如果您不希望结果中出现 RN,而不是顶部的 SELECT *,您可以指定所需的列

SELECT [Doctor], [Professor],[Singer], [Actor]
 From  (...) src
 Pivot (...) pvt

编辑 - 评论

如果你运行内部查询

Select *
      ,RN = dense_rank() over (partition by occupation order by name)
 From  @YourTable
 Order By RN

你会得到

Name        Occupation  RN
Jane        Actor       1
Jenny       Doctor      1
Ashley      Professor   1
Meera       Singer      1
Priya       Singer      2
Christeen   Professor   2
Samantha    Doctor      2
Julia       Actor       2
Maria       Actor       3
Ketty       Professor   3

RN 成为 Y 轴,Occupation 成为 X 轴,Name 是值。 枢轴按设计是聚合,因此我们只需要一个 Y 轴来执行分组。

【讨论】:

  • 谢谢@john-cappelletti!这似乎行得通。我需要研究正在发生的事情,因为我想了解它,而不仅仅是有一个可行的解决方案。我以前从未见过dense_rank,并且不熟悉“按名称按职业顺序划分”。最重要的是,我不明白这样做是如何做到的,所以你可以使用“max”,因为显然你仍然使用 max。你能在你的回答中留下一些问题吗?谢谢一百万。
  • @Dave fyi row_number() 也可以。 Dense_Rank 将压缩欺骗
  • 非常感谢您的回答和补充说明!我的脑海中仍然有点动摇(我并不一直使用 SQL)* 但你给了我足够的学习和学习。如果您有任何喜欢的 PIVOT 教程/文章,请按我的方式发送!谢谢! *大多数情况下,我仍在努力弄清楚这一切如何让 MAX 毫无问题地使用。
  • @Dave 关于教程,很抱歉我不会提供太多帮助。当我有问题时(经常这样),我的第一站就是 SO。关于 ,RN = ... 这只是我采用的一种风格。更易于阅读和注释以进行调试。我讨厌 {expression} 作为 Column_Name 格式。阅读长表达式只是为了发现它不是感兴趣的对象。另一方面,Gordon Linoff 讨厌我的格式。归根结底,这是最适合您的方法。继续学习并询问是否有更好的方法:)
猜你喜欢
  • 1970-01-01
  • 2013-03-24
  • 2019-07-03
  • 2012-02-20
  • 1970-01-01
  • 2016-10-16
  • 2010-11-23
  • 2014-12-30
  • 2010-11-17
相关资源
最近更新 更多